Ok, this took me a bit to figure out.
TL;DR: chaining comparisons use short-circuiting thus the comparison in OP does not reach == false
. More readable is to use !
:
!(typeof(a) <: Array{<:AbstractArray, 1})
Long story:
In hind-sight it shouldn’t have taken so long to figure out. Here how I went about it:
Further reduced:
julia> Int <: Float64 == false
false
julia> (Int <: Float64) == false
true
julia> Int <: (Float64 == false)
ERROR: TypeError: in <:, expected Type, got a value of type Bool
Stacktrace:
[1] top-level scope at REPL[15]:1
Looking at the lowered code for the top example:
julia> Meta.lower(Main, :(Int <: Float64 == false))
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Int <: Float64
└── goto #3 if not %1
2 ─ %3 = Float64 == false
└── return %3
3 ─ return false
))))
which can be tidied up to give:
if Int <: Float64
false
else
Float64 == false
end
And that finally made it click for me: chaining comparison use short-circuiting (see Mathematical Operations and Elementary Functions · The Julia Language). Thus
Int <: Float64 == false # -> false
is not equivalent to
(Int <: Float64) == false
but to
Int <: Float64 && Float64 == false # (edited)
and as the first term is false, the second never gets evaluated.
Or put into another example:
julia> 5 < 4 > "haha"
false
julia> 2 < 4 > "haha"
ERROR: MethodError: no method matching isless(::String, ::Int64)