I am new to Julia and encountered a confusing result with nested where statements. However, I do not know if this is a bug or an intended (but ill-documented) behaviour. Here’s a snippet describing it:
julia> MyAlias{A,B} = Tuple{A,B} where {B,A}
Tuple{A,B} where A where B
julia> MyAlias{1,2}
Tuple{2,1}
I was expecting to get a Tuple{1,2}, as I thought that the only purpose of where was to annotate yet unknown parameters. Obviously, this is easily fixed by using parameters in the right order (where {A,B}), but still, it’s confusing.
This does not happen if I try to reproduce it with a function, so it might be a bug:
julia> myprint(::Tuple{A,B}) where {B,A} = print(A,B)
myprint (generic function with 1 method)
julia> myprint((1,1.0))
Int64Float64
I am using julia 1.0.0:
julia> versioninfo()
Julia Version 1.0.0
Commit 5d4eaca0c9 (2018-08-08 20:58 UTC)
Platform Info:
OS: macOS (x86_64-apple-darwin14.5.0)
CPU: Intel(R) Core(TM) i5-4258U CPU @ 2.40GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.0 (ORCJIT, haswell)
Environment:
JULIA_EDITOR = atom -a
JULIA_NUM_THREADS = 2
The precedence of where is indeed confusing, though as I recall, other choices led to some pretty strange behavior in function declarations.
What you’re supposed to do in this case is
const MyAlias{A,B} = Tuple{A,B}
without the where. I agree this is confusing. It’s probably legacy from when there used to be a typealias keyword. Essentially the = operator is special for type aliases.
Note also that Tuple is special in that it is the only covariant type in the language.
I’m curious what opinion the core devs have on the lack of anything to indicate the fact that the type parameters are undefined variables lacking a where clause in these cases.
I did not realize that the where was not necessary in this case. It is indeed cleaner (and less error-prone) with this syntax.
There’s still some confusing stuff:
julia> Type1 = Tuple{A,B} where {A,B}
Tuple{A,B} where B where A
julia> Type2 = Tuple{A,B} where {B,A}
Tuple{A,B} where A where B
julia> Type1 == Type2
true
julia> Type1{1,2}
Tuple{1,2}
julia> Type2{1,2}
Tuple{2,1}
julia> Type1{1,2} == Type2{1,2}
false
julia> Type3{X,Y,Z} = Tuple{A,B} where {A,B}
Tuple{A,B} where B where A
julia> Type3{2,3,4}
ERROR: too many parameters for type
Stacktrace:
[1] top-level scope at none:0
It looks like the parameters on the LHS are just ignored. Better would be to error if there are any parameters at all.