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.lyc...@gmail.com 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
>>>
>>
>>

-- 

Reply via email to