Hi all,
I suddenly had a “metaphysical” doubt when learning about the @static
macro.
I imagined that such macro could be used to completly evaluate a given expression and replace it by its result at compile time. It cannot.
Then I though that maybe @eval
would do that. But trying
julia> a=1
julia> f() = a
julia> g() = @eval f()
julia> a=2
julia> g()
2
one can see that it wont do.
Finally, I got a way to do it through some macro like:
macro capture(expr); eval(expr); end
julia> a=1
julia> f() = a
julia> g() = @capture f()
julia> a=2
julia> g()
1
It works.
Now, I’m wondering:
Is there any uses cases for this functionality?
If yes, is there some similar macro in Base?
If not, is there another, more common, way to have this behavior?
Thanks.
You can splice in a value directly
@eval f() = $a
1 Like
But what if function f
instead of returning a global variable, makes a check of the system by running some program, which one intends to be ran only once at compile time?
What do you mean by “compile time”. If it’s just a cache, then do just that. You can even write a macro to do it. If it depends on input types and by compile time you mean inference time, then it can be valid to use generated function in some cases as long as you are not calling any functions defined after this function and you can handle the case where the function is compiled multiple times.
I mean something like “parsing time” or “precompilation time”. I mean something that does not depends on future inferences of g()
function due to it being called with new argument types.
But I guess I found the way this is usually done, it uses your first answer indeed but applied to the definition of g()
:
julia> a=1
julia> f() = a
julia> @eval g() = $(f())
julia> a=2
julia> g()
1
@eval
must contain everithing since g() = @eval $(f())
does not do what I want.
I imagine that this is useful, for example, for using some constant, that is computed by a piece of Julia code, guaranteeing that such constant is computed only once, e.g.,
h(x) = x + sin(1.23)
versus
h(x) = x + @capture sin(1.23)
or
@eval h(x) = x + $(sin(1.23))
which entail different @code_llvm
…
Thanks
Sure, I stand corrected.
(I initially tried doing g() = @eval $(f())
that’s why it didn’t work.)