Or, if you do not trust union splitting, you can have one global with a boolean to indicate if the function was already called or not; and the global with the Ref starting with a dummy/undef value.

If your function has some input, you might better avoid at all this global state, and wrap the constant precomputed in the input, such that the function is completely self-contained. Something like:

julia> struct MyInput
x::Vector{Float64}
constant::Float64
end
julia> MyInput(x::Vector{Float64}) = MyInput(x, length(x)*sum(x)) # invented a calculation for the constant
MyInput
julia> input = MyInput(rand(3)) # here the constant is computed
MyInput([0.607776859483833, 0.630463715553019, 0.01606684134650216], 3.762922249150063)
julia> function foo!(input)
(;x, constant) = input
x .= constant .* x # mutates the `x` entry of input
end
foo (generic function with 1 method)
julia> foo!(input)
MyInput([2.2870170670702663, 2.372385942536272, 0.06045827477631713], 3.762922249150063)
julia> foo!(input)
MyInput([8.605867405864627, 8.92710384674058, 0.22749978730103176], 3.762922249150063)