Where does where go?

I generally write function signatures with the where-clause outside of the arguments list. Is there any reason why one would put that inside the function signature? e.g.

foo(x::T where T) = 1
foo(x::T) where T = 2
foo(1)   # 2

But then they seem to be equivalent as it reports only 1 method:

julia> foo
foo (generic function with 1 method)

It makes a difference for something like

foo(x::T where T, y::T where T)
foo(x::T, y::T) where T

The first takes any 2 arguments of any types, while in the 2nd, the 2 arguments need to have the same type.


It also matters if you want to use the type T in the function body:

julia> f(::T where T) = T
f (generic function with 1 method)

julia> f(1)
ERROR: UndefVarError: T not defined
 [1] f(::Int64) at ./REPL[1]:1
 [2] top-level scope at REPL[2]:1

julia> f(::T) where T = T
f (generic function with 1 method)

julia> f(1)

This is

f :: (T -> T) where T
f :: (T where T) -> T 

Hi @thautwarm - what do you mean?

Hi, I meant the scope of the fresh type variable.
Technically, where is the same thing as the forall quantifier.
Check this wiki subsection for more about the scope.

1 Like