Automatically make all fields of an (immutable) struct concrete type

I often find myself introducing a bunch of type parameters to make working with the declared struct faster. For example, I would write

struct Foo{TA, TB}
a::TA 
b::TB 
end

and the only purpose of TA and TB is to make sure Foo is a concrete type. If wrote

struct Foo
a
b
end

this this would not be the case, because field :a and field :b are of type Any.

Is there any way to automatically introduce template parameters for all the fields? Ideally, I would like to be able to write something like

struct Foo
a::Real
b::Integer
end

as a shorthand for

struct Foo{TA<:Real, TB<:Integer}
a::TA 
b::TB 
end

At least for immutable structs I don’t see why a field should ever have a non-concrete type (?)

In summary:

  1. Is there a less verbose way to “concretize” the types of all fields in a struct?
  2. Why does Julia allow abstract field types for immutable structs?
1 Like

This can be implemented in a macro. QuickTypes.jl has it, quoting the readme:

using QuickTypes

@qstruct_fp Plane(nwheels, weight::Number; brand=:zoomba)
3 Likes

As for the second question, this can be useful in a couple of situations.

  • One is, when you want to avoid generating too much code. Then it can make sense to avoid specialization on fields that are irrelevant for performance hot spots.

  • Another one is, when you want to wrap things that are technically of different type into a single concrete type. Like

struct Predicate
     f
end
(p::Predicate)(x) = p.f(x)::Bool

@assert typeof(Predicate(isfinite)) ==  typeof(Predicate(isnan))