Is there a way to make this work in Julia:
##
function relative(t::Type{Int64})
Float64
end
function relative(t::Type{Int32})
Float32
end
struct Foo{T}
a::relative(T)
b::T
end
x = Foo{Int64}(2.0, 1)
This is a common and useful pattern in c++.
jbrea
March 7, 2023, 9:25pm
2
What about:
relative(::Int64) = Float64
relative(::Int32) = Float32
struct Foo{T1,T2}
a::T1
b::T2
end
Foo(a, b::T) where T = Foo{relative(b), T}(a, b)
x = Foo(2.0, 1)
y = Foo(2.0, Int32(1))
2 Likes
sgaure
March 7, 2023, 9:43pm
3
Computed field types have been an issue for several years. It’s on the 2.0 milestone list.
opened 11:24PM - 12 Sep 16 UTC
closed 05:27PM - 30 Mar 23 UTC
speculative
types and dispatch
Currently, we can perform a limited set of logic in the type definition, such as… :
``` julia
type A
a::eltype(Vector{Int})
end
```
but we can't involve a type parameter, such as:
``` julia
type B{V <: AbstractVector}
a::eltype(V)
end
```
AFAICT, at the moment the field types `A.types` is calculated when the type is defined and type parameters are inserted into the correct slots as they become known.
However, it would be nice if the types could be calculated by arbitrary inferrable or `@pure` functions. Another simple example (close to my heart) would be:
``` julia
immutable StaticMatrix{M,N,T}
data::NTuple{M*N, T}
end
```
However this results in an error that multiplication is not defined for `TypeVar`s. Instead, I need all of this code:
``` julia
immutable StaticMatrix{M,N,T,L}
data::NTuple{L, T}
function StaticMatrix(d)
check_params(Val{L}, Val{M}, Val{N})
new(d)
end
end
@generated function check_params{L,M,N}(::Type{Val{L}}, ::Type{Val{M}}, ::Type{Val{N}}) # could also be `@pure` in v0.5
if L != M*N
error("Type parameters don't match")
end
end
```
and my users need to foist around the redundant `L` paramater when they need to specify a concrete type.
For abstract types, I'm hoping that inference itself could still be used to come up with a least-pessimistic approximation of each field, or otherwise just use `Any` when that's not possible. If that makes it difficult to avoid regressions, straight types (combinations of types and the relevant `TypeVar`s with `apply_type` but no other functions) could keep functioning as they currently do.
2 Likes
jbrea:
struct Foo{T1,T2}
a::T1
b::T2
end
Foo(a, b::T) where T = Foo{relative(b), T}(a, b)
If you want this to be a guarantee rather than just a convenience thing you can also make it an inner constructor so its impossible to construct the object in an “inconsistent” state:
struct Foo{T1,T2}
a::T1
b::T2
Foo(a, b::T) where T = new{relative(b), T}(a, b)
end
2 Likes