Thing is, what is N1+1
? The language doesn’t know the type of N1
, so it doesn’t know what +
does. We could constrain N1
to a concrete type, and in that case there is potential to infer N1+1
. But a consistent structure needs the +
method to be pure or never change, which is not guaranteed. Types cannot change structure because there’s no good way to handle existing instances and compiled code. The straightforward rule is requiring every parameter to be provided rather than computed from others.
ComputedFieldTypes doesn’t have this issue because the @computed struct
header is only a shorthand inner constructor, not an actual type.
julia> c::Int = -1; function impure_add(a, b) a+b+c end
impure_add (generic function with 1 method)
julia> @computed struct B{N1}
a::NTuple{impure_add(N1, 1), Int}
end
julia> fulltype(B{1})
B{1, 1}
julia> c::Int = 0; fulltype(B{1}) # now specifies another type
B{1, 2}
Since there isn’t an inner constructor with all the parameters, you must use the shorthand and be careful about what it means at a given moment, or else you get cryptic errors:
julia> B{1}((1,2))
B{1, 2}((1, 2))
julia> c::Int = 1; B{1}((1,2)) # if you don't adjust properly
ERROR: MethodError: Cannot `convert` an object of type
Tuple{Int64{},Int64{}} to an object of type
Tuple{Int64{},Int64{},Int64}