The docs says:
Generated functions must not mutate or observe any non-constant global state (including, for example, IO, locks, non-local dictionaries, or using
hasmethod
). This means they can only read global constants, and cannot have any side effects. In other words, they must be completely pure.
I suspect that pools
in the following example is a non-local dictionary, thus prohibited. But this example seems to work, and frankly, I cannot imagine how it can break (not counting future threaded-compilation issues), because pools
is an append-only internal.
The example is a cache of vectors that is accessible with types as keys:
const pools = Dict{Type,Vector}()
function createpool(type::Type{T}) where T # Not exported
pool = Vector{type}()
pools[T] = pool
return pool
end
@generated function getpool(type::Type{T}) where T
if !haskey(pools, T)
createpool(T)
end
retval = pools[T]
return :($retval)
end
The trick allows compile-time cache resolution:
julia> @btime getpool(Dict{String,Symbol})
1.124 ns (0 allocations: 0 bytes)
0-element Array{Dict{String,Symbol},1}
Maybe the docs is too strict? Could somebody help me better understand the limitations of @generated?
A supported alternative solution would also be great!