> > Is there a clear language spec for macros, or is it still evolving? I > understand that relying on implementation to learn a language feature can > be risky. >
There is no formal spec that I am aware of. However, I don't remember any substantive changes except for this one in 0.5-dev: https://github.com/JuliaLang/julia/pull/14563 (which is fairly minor: macro-methods can now dispatch on number of arguments IIUC) There's one major proposal related to hygiene; no final decision on whether/when it will be accepted: https://github.com/JuliaLang/julia/pull/6910 (rebased in #10940) When I call retMacro(), I get an error saying "Macro definition not allowed > in local scope". What I tried to do in my earlier example (pre post) is to > hide the macro definition in a string and then parse and evaluate it to get > the same effect as the above function. Obviously the behaviour is > different. > Your earlier example works because `eval` always operates at module-global scope. Macro definitions, type declarations, and a handful of other things, are only allowed at global scope. > Does it mean every macro is its own type? > Yes (and further, on 0.5-dev all functions are internally represented as types) > Should it not be a predefined type like "macro" (just as there is type for > functions)? If macros are "pre-processed away", then there can't be an > independent existence for them? > Here's some more detail that will hopefully clarify. Macro invocations are represented as :macrocall expressions: julia> parse("@foo(1, 2)") |> dump Expr head: Symbol macrocall args: Array{Any}((3,)) 1: Symbol @foo 2: Int64 1 3: Int64 2 typ: Any The first step of lowering is to walk the AST to find all :macrocall expressions, call the corresponding macro-function -- exactly the function returned by `eval(Symbol("@foo"))` -- with the appropriate arguments, and paste the result expression into the AST. (see http://docs.julialang.org/en/latest/devdocs/julia/ for some more details) Finally, in 0.5-dev, if "returnMacro()" works as expected, then calling > myMacro("1+1") should return 2 (and not the parsed structure), isn't it? > The reason is does an additional evaluation? > No, `myMacro` is just a handle to the macro-function, exactly the same as `myMacro(x) = parse(x)`. There is no evaluation of the return expression when directly calling a macro-function. As I had mentioned in my first post, these questions are based on my > experience with Lisp and I am trying to digest the differences, if any. > > -Rangarajan > > On Tuesday, July 5, 2016 at 9:35:52 PM UTC+5:30, Isaiah wrote: > >> Anonymous functions are a bit incomplete / not-fully-integrated in 0.4, >> and I think this falls out as a consequence. >> >> You can simulate the result you want with: >> >> julia> function returnMacro() >> eval(parse(""" >> macro myMacro(anexpr) >> parse(anexpr) >> end >> """)) >> eval(symbol("@myMacro")) >> end >> >> julia> mymacro = returnMacro() >> (anonymous function) >> >> julia> mymacro("1+1") >> :(1 + 1) >> >> However, there have been significant improvements to anonymous functions >> in the nightly (0.5-dev), and the result is what you expect: >> >> julia> function returnMacro() >> eval(parse(""" >> macro myMacro(anexpr) >> parse(anexpr) >> end >> """)) >> end >> returnMacro (generic function with 1 method) >> >> julia> mymacro = returnMacro() >> @myMacro (macro with 1 method) >> >> julia> typeof(mymacro) >> #@myMacro >> >> julia> mymacro("1+1") >> :(1 + 1) >> >> That said, `mymacro` here is purely a function handle -- totally >> identical to writing `mymacro(expr) = parse(expr)`. There is no special >> behavior. >> >> (are you trying to do something specific?) >> >> On Tue, Jul 5, 2016 at 11:04 AM, Rangarajan Krishnamoorthy < >> [email protected]> wrote: >> >>> Consider this function: >>> >>> function returnMacro() >>> eval(parse(""" >>> macro myMacro(anexpr) >>> parse(anexpr) >>> end >>> """)) >>> end >>> >>> I assign the function's result to a variable: >>> mymacro = returnMacro() >>> >>> Then, typeof(mymacro) returns "Void". Is this correct? Because macros >>> are parse time entities, wouldn't it be better for "eval" to raise some >>> sort of exception? >>> >>> -Rangarajan >>> >> >>
