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
1 Like
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.
4 Likes
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.
1 Like
Honestly, I don’t know why f3(Sym{Float64}())
works. As far as I can tell, it’s equally nonsensical…
2 Likes
Agreed, seems like a valid issue to post / look for on the julia github.
1 Like
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.