semantics of `where {}` in parametric methods

question

#1

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.

Thanks,
-Tom


#2

The most recent version of the documentation (‘latest’) has a much better description of parametric methods: https://docs.julialang.org/en/latest/manual/methods.html#Methods-1

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

#3

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.

Thanks,
-Tom


#4

The latter is deprecated for the former.

It matters if you are doing “triangular dispatch” which is now supported. See some discussion at https://github.com/JuliaLang/julia/issues/3766.