In a package of mines I need to often create an empty Dict to which I later add elements. In order to avoid always allocating a new empty Dict, I thought about exploiting generated functions in this way:
@generated foo(x) = Dict{x,x}()
So now foo(0.0) is very fast an cheaper than always running Dict{Float64,Float64}(). Is this considered a good use of generated functions? Or is it an abuse and it’s prone to fail at some point?
Edit: contrary to what I wrote in the first version of the message, I’m more interested in Base.ImmutableDict rather than Dict.
Base.ImmutableDict doesn’t have the same problem as Dict (sorry, when writing the first message I didn’t consider I was simplifying too much):
julia> @generated foo(x) = Base.ImmutableDict{x,x}()
foo (generic function with 1 method)
julia> d1 = foo(0.0)
Base.ImmutableDict{Float64,Float64} with 0 entries
julia> d2 = foo(0.0)
Base.ImmutableDict{Float64,Float64} with 0 entries
julia> d1 = Base.ImmutableDict(d1, 3=>4)
Base.ImmutableDict{Float64,Float64} with 1 entry:
3.0 => 4.0
julia> d2
Base.ImmutableDict{Float64,Float64} with 0 entries
The question still holds: is this use of @generated fine? I don’t care the body of the function isn’t run exactly once, the important is that it isn’t always.
Embedding an object in the returned AST (or returning an object) is fine. Do note that the construction of the object cannot depend on any methods defined later, otherwise it’s fine.
Just to clarify, I mean that if you need to have, say, 5 distinct (mutable) objects, you have to create 5 distinct objects. It’s technically impossible to allocate memory only for one of them, but fill it with 5 different data, regardless of the features available in the language.