Walkthrough
The @concrete
macro can be tacked onto any struct
definition that isn't already concretely-typed. That's kinda all there is to it, but let's walk through some examples anyway to get a feel for it.
In this example, no type parameters are given, so they will be filled in automatically:
@concrete struct Whatever
a
b
end
julia> complex_whatever = Whatever(1+im, "It's pretty complex")
Whatever{Complex{Int64},String}(1 + 1im, "It's pretty complex")
But maybe we don't want to show the type parameters, since we never cared much about them in the first place. If we want our struct
to print a little more succintly, we can add the terse
keyword. Now it will print as if we never added the @concrete
macro.
@concrete terse struct PrettierWhatever
a
b
end
julia> pretty_whatever = PrettierWhatever(1+im, "It's still pretty complex")
PrettierWhatever(1 + 1im, "It's still pretty complex")
The full type information is still available for inspection with the typeof
function, though.
julia> typeof(pretty_whatever)
PrettierWhatever{Complex{Int64},String}
More complicated type parameterizations are possible as well. Take this example of an array with two metadata fields attached. The type parameters for the array
field are provided but the name
field's type is left open. The @concrete
macro will respect the given type parameters and concretely parameterize the name
field.
@concrete struct MetaArray{T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
array::A
name
end
Base.size(x::MetaArray) = size(x.array)
Base.getindex(x::MetaArray, i...) = getindex(x.array[i...])
julia> abed = MetaArray([8,10,2,5], "Abed")
4-element MetaArray{Int64,1,Array{Int64,1},String}:
8
10
2
5
We can also have type parameters that don't correspond to any field. In this example, the BananaStand
type is parameterized by the boolean value has_money
.
@concrete terse mutable struct BananaStand{has_money}
employees
manager
end
In this case, the constructor must be given with the has_money
parameter, just like it would need to be if we weren't using the @concrete
macro. Since the terse
keyword was give, the type will print exactly as it's specified: with the has_money
parameterization but no field parameterizations.
julia> the_banana_stand = BananaStand{true}(["Maeby", "Annyong"], "George Michael")
BananaStand{true}(["Maeby", "Annyong"], "George Michael")
julia> typeof(the_banana_stand)
BananaStand{true,Array{String,1},String}