No worries; if you are missing S-expressions too much, you might enjoy playing with https://github.com/swadey/LispSyntax.jl
On Wed, Jul 6, 2016 at 12:41 AM, Rangarajan Krishnamoorthy < [email protected]> wrote: > That was very helpful. Thanks for your patience. > > -Rangarajan > > > On Wednesday, July 6, 2016 at 9:39:56 AM UTC+5:30, Isaiah wrote: >> >> 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 >>>>> >>>> >>>> >>
