This is an MWE simplified from a real-world problem — I have a T <: NamedTuple
type, and would like to generate an value ::T
from functions that generate fields based on type, to be named appropriately.
using Random
struct Gen{T <: NamedTuple, R <: AbstractRNG}
rng::R # the original problem has a mutable field capturing a state, too
end
# convenience constructor
Gen{T}(rng::R) where {T <: NamedTuple, R <: AbstractRNG} = Gen{T,R}(rng)
# field generator: in the MWE, random
genfield(rng::AbstractRNG, ::Type{T}) where T <: Real = rand(rng, T)
# field generator for potentially missing
genfield(rng::AbstractRNG, ::Type{Union{Missing, T}}) where T =
rand(rng) < 0.5 ? missing : genfield(rng, T)
# THIS is the problematic function
gen(g::Gen{T}) where T =
T(ntuple(i -> genfield(g.rng, fieldtype(T, i)), fieldcount(T)))
g = Gen{NamedTuple{(:a, :b), Tuple{Int, Union{Missing, Float64}}}}(Random.GLOBAL_RNG)
@code_warntype genfield(Random.GLOBAL_RNG, Union{Missing, Float64})
@code_warntype gen(g)
With lot of the output cut,
julia> @code_warntype genfield(Random.GLOBAL_RNG, Union{Missing, Float64})
Body::Union{Missing, Float64}
julia> @code_warntype gen(g)
Body::Any
julia> VERSION
v"1.1.0-DEV.439"