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))()
    for arg in args
        push!(fn.args[2].args[1].args, esc(arg))
    return fn

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

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

It generate an error

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?


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