Yes, that is exactly the kind of example that I'm referring to. (As is the example that started this thread as well.) In all other cases, x::T is covariant in the sense that it allows typeof(x) <: T. But in an argument list when T is a type parameter to the same method, x::T is instead invariant in the sense that it only allows typeof(x) === T.
To me, this is a much bigger (and completely different kind of) difference than between using :: as a type declaration and type assertion. Now that I know this, I'm starting to doubt what I thought that I knew about type parameters in other cases. How about f{T}(x::AbstractArray{T}) = T Does this accept subtypes of AbstractArray{T}? It turns out that it does. But how do I know? I suspect that the pragmatic rule that Julia follows is that each type declaration that involves a type parameter T must in itself determine a unique possible value for T based on the type of the method arguments. Jeff or Stefan: Care to comment? On Friday, 16 May 2014 11:48:29 UTC+2, Mauro wrote: > > Here is an example of the difference Toivo refers to (I think): > > > julia> foo{T<:Real}(a::Array{T},b::T) = T > foo (generic function with 1 method) > > julia> bar(a::Array{Real},b::Real) = Real > > > bar (generic function with 1 method) > > julia> aR = Real[1,2]; aI = Int[1,2]; > > > > julia> foo(aR, 5) > ERROR: no method foo(Array{Real,1}, Int64) > > julia> foo(aI, 5) > > > Int64 > > julia> bar(aR, 5) > > > Real > > > When calling foo(aR, 5), then T is set to Real. Now in case of > parameterized functions this means that typeof(b)===T, i.e. typeof(b) > must be Real. (which in this case is never possible as Real is an > abstract type). This contrasts to bar where only the weaker constraint > typeof(b)<:Real is needed, i.e. a isa relation. > > Thus, Toivo's complaint is that in function definitions :: usually means > `isa` whereas for parameterized functions it means type equality `===`. > However, I think this realisation does not make the :: situation worse > than it already is. :: has different meanings depending on context: > ditto when in function declarations, then in function bodies it can also > be a sub-type-assert, or a type declaration of a variable in the sense > of check-and-convert (if check fails). So, three meanings of :: are > possible. > > As an aside, in the issue about "function return type declarations" > https://github.com/JuliaLang/julia/issues/1090 it is suggested to add > syntax like f(a)::Int = 5 to declare that f returns an Int. The > discussion there suggests that there :: will have the check-and-convert > semantics. Thus a line like this could contain all three meanings of :: > > f{T<:Real}((a::Array{T},b::T,c::Integer)::Complex = ... > > ! > > On Fri, 2014-05-16 at 08:15, tomas....@gmail.com <javascript:> wrote: > >> But do you agree that the usage of x::T as a formal parameter is quite > > different when T is a type parameter compared to when it is a plain > type? > > > > I'm not 100% sure I grok what you're getting at, but *if *what you're > > asking is whether I see a difference between foo(x::Real) and > > foo{T<:Real}(x::Array{T}), then really no - I don't. > > > > I just the latter as shorthand for defining a function with a whole > bunch > > of methods - foo(x::Array{Int64}), foo(x::Array{Float64}), etc etc - > with > > the same Julia implementation. They will still, just as the former for > > foo(x::Int64) and foo(x::Float64), be compiled to different versions, > > strongly typed to the runtime type of the argument, and I could get > exactly > > the same behavior without parametric methods by copy-pasting the > > implementation and using different specific type signatures. I'd need > one > > for every subtype of Real, so of course this isn't feasible in practice, > > but the way I look at it the difference is really mainly syntactic > sugar. > > > > The possibility to do diagonal dispatch with the help of type parameters > is > > also syntactic sugar - I could just as easily define bar(x::Int64, > > y::Int64) etc for all real types, but with no methods for bar that take > > arguments of different kinds, as define bar{T<:Real}(x::T, y::T). Again, > > this would mean an insane amount of code duplication, so I'm really glad > I > > don't *have* to code this way, but I certainly could if I for some > wicked > > reason wanted to. > > > > There is of course one thing that differs profoundly: if you define > > foo{T<:Real}(x::Array{T}) and then someone else comes, later on, and > > defines a new subtype to Real, your definition just works. Had you done > it > > without type parameters, it of course wouldn't have worked without also > > adding a specific implementation for foo(x::Array{MyNewRealType}). > > > > // Tomas > > > > On Thursday, May 15, 2014 10:03:12 PM UTC+2, Kevin Squire wrote: > >> > >> FWIW, I really appreciate you pointing out the different uses of :: > Toivo. > >> Along with the different meanings of parameterizations in types and > >> functions, this is another area I haven't been clear about (and I > wasn't > >> even aware of it until you pointed it out). > >> > >> Cheers! > >> Kevin > >> > >> > >> On Thu, May 15, 2014 at 11:49 AM, Toivo Henningsson > >> <toiv...@gmail.com<javascript:> > > >> > wrote: > >> > >>> > >>> > >>> On Thursday, 15 May 2014 10:59:07 UTC+2, Tomas Lycken wrote: > >>>> > >>>> it silently uses :: in a different sense than anywhere else in the > >>>>> language > >>>> > >>>> > >>>> I started writing a reply here, but realized it would be more > >>>> instructive to have it as an IJulia notebook, where we can actually > inspect > >>>> the values of various statements along the way - take a look here > instead: > >>>> > http://nbviewer.ipython.org/github/tlycken/IJulia-Notebooks/blob/master/ > >>>> A%20more%20thorough%20look%20at%20Julia's%20%22double% > >>>> 20colon%22%20syntax.ipynb > >>>> > >>>> I hope it makes things a little clearer. I tried to base it on the > >>>> relevant section on `::` in the manual (http://docs.julialang.org/en/ > >>>> latest/manual/types/#type-declarations) and expand it with more > >>>> examples etc, so I hope it's possible to see the connections. > >>>> > >>> > >>> / Toivo > >>> > >> > >> > > -- > >