In the documentation of Julia v1.0 there is almost nothing about escaping in a macro. I tried a simple debug function, which can be inserted at critical points of a function. It should print an expression or variable name, and its current value. I defined a macro in a module, but I get weird messages (b = c =) at loading the module, and within a function only the last value of several calls to the macro is actually shown in REPL. If I type in REPL @db(1+2) or a = falses(2); @db(a) I get the desired effects.
Could anyone point to relevant information or tell, how I such simple macro should be written?
module TestModule
export @db, f
macro db(x) # only works in REPL, single call in a line
print(x," = ")
return :($(esc(x)))
end
function f()
b = falses(3)
@db(b)
c = trues(5)
@db(c)
end
end
I tried to open a Julia issue about the need of improved documentation of esc(), and about its unexpected behavior, but the issue was immediately closed.
This isn’t really an escaping issue at all. Macros are source code transformations, and they get run before your code executes. As a result, your print statements are being run when the macro is run, during the parsing and lowering of your source code.
If you want the macro to actually cause something to be printed at run-time, then that println needs to be inside the expression that the macro returns.
Aah, I had not tested my macro from within a function.
I think that
macro db(x)
return esc(quote
println($"$x = ", $x)
end)
end
should do what you want.
But I, too, feel that I’m mostly trying things around until something works without a deep understanding. A deep and rigorous tutorial would be helpful.
If you are ever confused about what your macro is doing, remember to use @macroexpand to see the code that it will give (though I do wish the output of this were easier to ready).
I would argue that the documentation is “decent”, even if it could be improved (which is generally true for most documentation).
Escaping is tricky (because it involves hygiene), and more examples could always help, but most of the tools that were suggested in this topic are documented with examples.
Maybe the documentation is good for experts, like you guys, but for a novice user it is just confusing. E.g. I could not find a description of the construct $“…”. The function esc() is said to be " Only valid in the context of an Expr returned from a macro". It is not clear, we can use it in assignments to local variables. So, where is it allowed? And so on…
I would read through the whole chapter since just spot-reading a particular subsection will not give you the complete picture of meta-programming in Julia.
Macros are tricky, especially when it comes to hygiene. I agree that more documentation would be nice, especially in the form of tutorials, and I guess those will appear in due time now that we have a stable release.
Also, don’t underestimate what you can learn from just reading the source. Base and the standard libraries have examples of complex macros, usually written by people who know Julia well.
That said, perhaps a novice user should wait a while before writing macros. They are not at all essential to using the language and even writing complex and powerful libraries.
The link above takes you there directly, so possibly that part?
I am not sure I agree; perhaps you could show us a language where this is simple. Eg in C, it is rather complex, in Common Lisp it would be simpler than Julia because that language does not have hygiene by default (so more complex macros need to work around that).
I have not seen a language where macros of any kind are novice material.
You are the best expert of missing documentation. Please make a pull request to propose a good example in the right place. However, be prepared to iterate because it seems that a lot of people have an opinion on this matter.
I read that section, too thoroughly. It says that “Julia allows interpolation of literals or expressions into quoted expressions. Interpolation is indicated by a prefix $ .” Accordingly, (and those are the examples given) you can write $a, $(exp), and $:(expr).
There is nothing about the construct of $“…”. This is what I missed, or overlooked. What does it stand for?