Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typealias and generic constructors #759

Closed
aviks opened this issue Apr 24, 2012 · 15 comments
Closed

typealias and generic constructors #759

aviks opened this issue Apr 24, 2012 · 15 comments
Assignees
Labels
kind:bug Indicates an unexpected problem or unintended behavior needs decision A decision on this change is needed

Comments

@aviks
Copy link
Member

aviks commented Apr 24, 2012

I'm trying to create a typealias for a particular parameterised type, and a subsequent constructor for the aliased type. However, the method definition fails with an error "not a generic function".

julia> type Foo{T<:Real}; a::T; end

julia> typealias Bar Foo{Int}
Foo{Int64}

julia> function Bar(x::String); Bar(int(x)); end 
in method definition: not a generic function

julia> function Bar(x::String); Foo{Int}(int(x)); end 
in method definition: not a generic function

Strangely, if I define a differently named function with the same arguments, the earlier definitions start working. Therefore, this seems like a bug to me. Continuing on the same session...

julia> function tee(x::String); Bar(int(x)); end

julia> tee("1")
Foo(1)

julia> function Bar(x::String); Bar(int(x)); end 

julia> Bar("1")
Foo(1)

julia> 
@aviks
Copy link
Member Author

aviks commented Apr 24, 2012

Some further experiments suggest that it is not the definition of tee above that causes the error to go away, but the actual call to tee("1") . Seems to be an error in type inference now.

@JeffBezanson
Copy link
Sponsor Member

There is some lazy allocation happening where a type does not "become" a generic function until an instance has been constructed via an "official" constructor. This is not supposed to be visible, so it's a bug, but I'm also not sure we intended to allow defining methods for specific type instantiations after the type declaration.
The syntax function Foo{Int}(...) clearly does not work for this, and the typealias is basically a clever hack to get around that syntactic limitation. I would just use inner constructors for now.

@StefanKarpinski
Copy link
Sponsor Member

Are all types, even abstract ones, able to serve as generic functions to construct objects? That's something I've sometimes thought we should support.

@aviks
Copy link
Member Author

aviks commented Apr 25, 2012

My constructors are a little more complex, eg: function Bar(x::String, y::Integer); Bar(int(x)+100 * y); end etc. I was having problems getting dispatch working with inner constructors of this type, with the parameterisation I stated above. I was getting 'method_missing' errors, even when it looked like I had the methods defined. I'll try to extract a replication testcase. That was when I moved to outer constructors.

The workaround I have in mind right now is to use function bar(...) rather than function Bar(...) to create the objects. Would you consider that to be a reasonable path?

In the larger scheme of things, the confusion, in my mind, is that an outer constructor looks and feels like a normal function, but is clearly not. That probably needs some explaining in the docs...

@JeffreySarnoff
Copy link
Contributor

Does Julia lend itself to allowing abstract types to serve as 'abstract' generic functions that construct abstract objects, objects that are semi-realized and in some other situation may become fully type-informed or generic-function-ally complete; and so be instantiated?

Pragmatically, that may be a seamless and robust way to offer aspect-oriented components; and maybe other sorts of semi-realized objects benefit from partial evaluation and the like in a way that improves the performance|reliability|elegance of the object instances they realize.

@StefanKarpinski
Copy link
Sponsor Member

I have no idea what this question means. Can you dumb it down a bit?

@pao
Copy link
Member

pao commented Apr 26, 2012

Also probably better to discuss that on -dev where more people will see it.

@JeffBezanson
Copy link
Sponsor Member

That is an interesting idea. It's potentially useful even in some trivial cases, like having a nil that can be a list of potentially any type.

One way to describe this in the julia model, if I understand the question correctly, is having a value whose actual type is Any. While it has that type it can only be passed to contexts that are fully polymorphic, e.g. assigning an element into a cell array. Then later perhaps its type changes.

But I think this would be very problematic, since right now the actual, concrete types of values form a "bedrock" we rest on all over the place. If even an actual value can lack a definite type, we are really out to sea. At least for now, we are much better off modeling this with a mutable field that takes on values of different types.

We could maybe do a trivial case of this, namely allowing values of indefinite type provided that type is never refined! This would at least handle nil, but of course otherwise totally lacks the functionality you're talking about.

@JeffreySarnoff
Copy link
Contributor

(before posting -dev)

"Are all types, even abstract ones, able to serve as generic functions to construct objects?" - Stefan Karpinski #759

Julia has two kinds of type: abstract and concrete. "..concrete types may not subtype each other: all concrete types are final.." Every supertype is an abstract type; and any [well formed] abstract type could be [one of] the supertype[s] [contributing to] that elaborates, constrains, or otherwise guides the nature of some concrete type.
That every 'final' type is a concrete type situates 'concrete type' within Julia's perspective.
That every 'concrete type' is final constrains the nature of supertype in a manner helpful within Julia.

Concreteness with respect to types is as is full realization with respect to ability-to-instantiate objects. Objects obtained with a [generic via] concrete type are 'concrete objects' [so defined, there no other 'concrete objects'].

Some objects are 'concrete objects' ... consider allowing Julia another kind of object, an 'abstract object' offering semi-realized 'concreteness' (an object that is not yet complete and may be completed). Any 'abstract object' becomes completed as it obtains whatever may be required to finalize one or more 'concrete object' instances.

Does the design of Julia lend itself to allowing the introduction of 'abstract generic functions' (functions that construct semi-realized, 'abstract objects') to be obtained from 'abstract types' in a way reflective of how 'generic functions' are obtained from 'concrete types'?

The performance|reliability|elegance of some objects may improve when they are instanced with the completion of an 'abstract object'. Also, this may be a more seamless, robust way to offer aspect-oriented components [software encapsulations that automagically adorn other code at just the right places to make it better in some aspect; e.g. enforced bounds checking, improved numerical stability, temporarily instrumenting code].

@JeffreySarnoff
Copy link
Contributor

The above is really not -dev sort of question -- its more a request for some Julia specific understanding. Does the language design (not the current code) allow a way to approach such an extension? Either way, Julia is well-positioned going forward. Congratulations.

@pao
Copy link
Member

pao commented Apr 27, 2012

That sounds ideal for julia-dev, actually; right now we're pinging the bug reporter on every post even though this discussion has nothing to do with the bug. But ultimately it's up to Stefan and Jeff where the discussion happens :D

@JeffBezanson
Copy link
Sponsor Member

The -dev list is fair game for any sort of julia-related or julia-almost-related discussion.

@mattjj
Copy link

mattjj commented Sep 19, 2012

I may be misunderstanding something, but is this supposed to work?

julia> typealias Foo Array{Integer,1}
Array{Integer,1}

julia> Foo() = [1,2,3]
invalid method definition: not a generic function

That's on 5b5aeb7

@ianfiske
Copy link
Contributor

@mattjj, I think that you are trying to define function to have the same name as a type, which is only allowed for constructors. See http://docs.julialang.org/en/latest/manual/functions/ and search for the word 'compact' to read about the compact assignment form for defining functions.

@mattjj
Copy link

mattjj commented Sep 20, 2012

Actually, I am trying to write a constructor for the type Foo (which is defined with a typealias); defining the constructor it in compact form or long form doesn't seem to make a difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug Indicates an unexpected problem or unintended behavior needs decision A decision on this change is needed
Projects
None yet
Development

No branches or pull requests

7 participants