I’m learning Julia from various sources. I’m also reading code to get an idea of how a good Julia codebase is structured (suggestions welcome, BTW). I’ve come across constructs like this:
TimeNode{V,T}(g::AbstractGraph, key::V, timestamp::T) where {V} where {T} = TimeNode(num_active_nodes(g) + 1, key, timestamp)
Obviously this is a parametric method definition, but I’ve had difficulty finding a clear rigorous explanation of the where keyword—or, for that matter, the syntax and semantics of such definitions. The closest is in the Parametric Methods section of the Julia reference manual, but that gives examples without a careful explanation.
I understand that where {V<:X) constrains V to be a subtype of X, but not what where {V} alone does. Does order matter? Does order matter in the {V,T} clause? How do the semantics change if one of these is missing? etc.
Best I can tell, where {V} binds the concrete type of the function’s argument to a variable V visible within the function’s scope.
function mytypeof(x::T) where {T}
return T
end
julia> mytypeof(2.0)
Float64
Additionally, where constrains the type signature of all corresponding arguments to the same concrete type, while annotating individual arguments does not.
f1(x::Number, y::Number) = x + y
f2(x::T, y::T) where {T<:Number} = x + y
julia> f1(2, 2.0)
4.0
julia> f2(2, 2.0)
ERROR: MethodError: no method matching f2(::Int64, ::Float64)
Closest candidates are:
f2(::T<:Number, ::T<:Number) where T<:Number at REPL[11]:1
Thanks. A few more questions. What’s the difference between:
mytypeof(x::T) where {T} = T
and mytypeof{T}(x::T) = T
From examples I’m guessing that the two are equivalent. I’m also guessing that the order of the where clauses doesn’t matter when you have multiple type parameters.