So it is clear that in the macro our argument changed (got evaluated) and in the function it stayed intact. Could you please point me to the part in the docs which describes this behavior?
When a macro is invoked, the commands recorded in the macro are first modified by replacing formal parameters (${arg1}, âŚ) with the arguments passed, and then invoked as normal commands.
And how does it answer what I asked? Try replacing formal parameters with actual argument just like it says in the docs and see what happens: message("Mac: {${VAR}}") ==> message("Mac: {\\$\\{something\\}}")
And that should print exactly the same as with function.
Nope, it means that the content of the macro first has a replacement of its formal (named) parameters expanded. Then the code is executed. This is why this code doesnât work:
macro (foo arg)
if (arg) # Macro arguments are not variables, so this doesn't care about what it looks like it cares about
message("arg: ${arg}") # prints `arg: 0` because this is replaced by the macro argument value
endif ()
endmacro ()
set(arg 1) # What that `if` sees
foo(0)
If foo was instead a function, the argument exists as a variable and the if would end up in the else() branch.
Sorry, but I still fail to see how any of it explains the evaluation of the argument. Letâs get the outer variable out of the way and simplify the calling code to this:
So we have a literal replacement in case of macro, so our argument should go directly to where it is mentioned (message("Mac: {${VAR}}")) but somewhere our argument gets evaluated and all â\â get dropped. I donât see how docs explain it, in my opinion docs are silent about this quirk hence this question: is it a doc deficiency or macroâs behavior is incorrect?
The macro replaces the value in the code, so the code now looks like fun("\$\{expanded_value\}") which is just a string with escapes (which avoid the expansion, but donât get printed). Given the quoting rules, losing the escapes doesnât surprise me, but I donât know which path actually does that. I also donât know how to write documentation for this beyond what is already stated: macro arguments are expanded and then the code is executed after expansion. I suppose that an explicit note about that this may mean an extra layer of escaping is necessary depending on the usage of the argument in the macro body is useful, but I can see that as just leading to more confusion too.
Really, just avoid macros unless you need the âaffects the calling scopeâ behavior and use functions for everything else.