abstract type Def{T} end
struct YY <: Def{Number}
end
f1(x::Def{<:T}) where T = T
f2(x::Def{T}) where T = T
julia> f1(YY())
ERROR: UndefVarError: T not defined
Stacktrace:
[1] f1(::YY) at ./REPL[3]:1
[2] top-level scope at REPL[5]:1
julia> f2(YY())
Number
Why f1(YY()) doesn’t work?
But the following works:
julia> struct Sym{T}
end
julia> f3(x::Sym{<:T}) where T = T
f3 (generic function with 1 method)
julia> f4(x::Sym{T}) where T = T
f4 (generic function with 1 method)
julia> f3(Sym{Float64}())
Float64
julia> f4(Sym{Float64}())
Float64
No answer here, but interested: what are f1 and f3 for?
Also:
julia> f3(Sym{Number}())
ERROR: UndefVarError: T not defined
Stacktrace:
[1] f3(::Sym{Number}) at ./REPL[2]:1
[2] top-level scope at REPL[5]:1
Actually, they work the same:
julia> f3(Sym{Number}())
ERROR: UndefVarError: T not defined
In the definitions of f1 and f3, we have something like: “the parameter of the input type is a subtype of T. Return T”. No further information is given about what T is or could be, so what should be returned? You could argue that the answer is Any, but I think it makes more sense to interpret this as an error, which is what’s happening. f2 and f4 make sense (“return the parameter of the input’s type”).
As a sidenote, for Def and YY, you probably meant (although I could be wrong)
struct YY{T<:Number} <: Def{T} end
I.e. keeping the type parameter on YY, but making sure it is always a subtype of a Number. By restricting to an abstract type like you were doing (i.e. Def{Number} rather than Def{<:Number}) you might be losing some performance and/or flexibility in your application of this type that parameterized types can give.
It works on my Julia. And it still doesn’t answer my question, why it works on a struct (concrete type) but doesn’t work on a abstract type (Number)?
Thanks
I think that’s not really well defined. You’re asking for a type which is a supertype of Number. T=Number is an answer, but so is T=Any. I’m a bit surprised that it’s not an error, but maybe it’s hard to circumscribe when to throw the error.
Honestly, I don’t know why f3(Sym{Float64}()) works. As far as I can tell, it’s equally nonsensical…
Agreed, seems like a valid issue to post / look for on the julia github.
It is not nonsensical it does what it does it returns you the least upper bound. Which comes handy in dealing with covariant types. But the issue occurs when T is abstract type.