An confused error for the Marco for Expr to function

I try to use the macro

macro expr2fn(fname, expr, args...)
    fn = quote
        function $(esc(fname))()
            $(esc(expr.args[1]))
        end
    end
    for arg in args
        push!(fn.args[2].args[1].args, esc(arg))
    end
    return fn
end

Then I use :
@expr2fn(f, :((n1+n2+n3)), n1, n2, n3 )
f(0.1,0.2,0.3)
This is fine.

When I use like :
expr2=:((n1+n2+n3))
@expr2fn(test2_func, expr2, n1, n2, n3 )

It generate an error

Blockquote
LoadError: type Symbol has no field args
in expression starting at /Users/gangchen/Downloads/sample.jl:92
getproperty(::Symbol, ::Symbol) at sys.dylib:?
@expr2fn(::LineNumberNode, ::Module, ::Any, ::Any, ::Vararg{Any,N} where N) at sample.jl:65
#macroexpand#32 at expr.jl:107 [inlined]
(::Base.var"#kw##macroexpand")(::NamedTuple{(:recursive,),Tuple{Bool}}, ::typeof(macroexpand), ::Module, ::Expr) at none:0
top-level scope at sample.jl:92
include_string(::Module, ::String, ::String) at sys.dylib:?
include_string(::Module, ::String, ::String, ::Int64) at eval.jl:30
(::Atom.var"#188#192"{String,Int64,String,Bool})() at eval.jl:111
withpath(::Atom.var"#188#192"{String,Int64,String,Bool}, ::String) at utils.jl:30
withpath(::Function, ::String) at eval.jl:9
#187 at eval.jl:110 [inlined]
with_logstate(::Atom.var"#187#191"{String,Int64,String,Bool}, ::Base.CoreLogging.LogState) at logging.jl:395
with_logger at logging.jl:491 [inlined]
#186 at eval.jl:109 [inlined]
hideprompt(::Atom.var"#186#190"{String,Int64,String,Bool}) at repl.jl:140
macro expansion at eval.jl:108 [inlined]
macro expansion at dynamic.jl:24 [inlined]
eval(::String, ::Int64, ::String, ::String, ::Bool) at eval.jl:105
macro expansion at eval.jl:39 [inlined]
(::Atom.var"#172#173")() at task.jl:333

Any one know what happens and how to fix the problem?

It is impossible for macro to read from a runtime variable. If the value is know before runtime, just use the first one.

Even better, remove the quote from that argument.

Standard question: What are you trying to accomplish using a macro here? Are you passing expressions as arguments and using metaprogramming when you could pass function arguments instead?

2 Likes

Yes. An additional question, are there any method can transform Julia expr to a function? We hope it can be used in REPL and in functions.

Assuming your โ€œyesโ€ referred to my question: donโ€™t use expressions to pass functions. Use functions to pass functions.

What are you trying to accomplish? I think we may have an XY problem here.

1 Like