Why does this not work:
struct Y{T<:Integer}
y::T
Y(a) = new(a * 2)
end
Instead, you have to do this, which seems like a lot of ceremony:
struct X{T<:Integer}
x::T
X(a::T) where {T} = new{T}(a * 2)
end
Edit: search terms: ERROR: syntax: too few type parameters specified in "new{...}"
Looking through the manual, the expected form is something like this
struct Z{T}
z::T
Z{T}(a) where {T} = new(a * 2)
end
Z(a::T) where {T} = Z{T}(a)
Which I guess is nice because it is very explicit? But I think it's adequately implied by Y
above. It's nicer than X
, tho
Maybe it's because in general case type of 2*a
can differ from the type of a
. For example, what if a
is of the (non existent) type OddInteger
? In this case 2*a
is of the type EvenInteger
and how compiler should solve this case? Is it Y{OddInteger}(1)
or Y{EvenInteger}(1)
? Only you know, what you really want to see in this case.
I guess the issue is that I expect new
to act like a generic method or a type with a default constructor. With those, we don't specify the types in the code, we just provide values and Julia decides what the types will be.
With your example, I feel like I'd be more likely to mess it up if I'm forced to be explicit compared to if new
behaved more like a function.
(To be explicit, I expect a behaviour like:
struct A{T}
x::T
function A(x)
x1 = x * 2
new{typeof(x1)}(x1)
end
end
)
But this is not the behavior of Z
or X
structure, right? Because they more or less explicitly say new{typeof(x)}(x1)
Hmm, I guess Z
will just error in this case.
Maybe they both error.
Should put it in REPL :-)
Ah, after some consideration, I think I get the real reason, why you should be explicit.
I think that new
is really can infer types on its own, but default inner constructor is more complicated than that.
I think it's closer to A{T}(x) where T = new{T}(convert(T, f(x))
, and this gives you possibility to write expressions like Vector{Float64}(1)
. In your syntax A(x) = new(f(x))
everything will be fine till the moment, when you would need to call constructor with explicit type (like in Vector{Float64}
example). Since types infer from the result of calculation, construction of the form A{T}(x)
will be forbidden. And it would be nice until the moment when you need it.
In your last example:
julia> A{Int}(1)
ERROR: MethodError: no method matching A{Int64}(::Int64)
And it looks unexpected. So you can shoot yourself in a foot, but at least you have to make extra efforts for it.
Last updated: Dec 28 2024 at 04:38 UTC