I'm trying to create some examples of using (experimental) macros this way:
use experimental :macros;
macro cards_vars() {
(<hearts clubs diamonds spades> X~ 1..10).map: { "my \$$^x = False;" }
};
cards_vars();
say $hearts1;
This creates and runs the macro, and then checks if one of the variable defined exists. But I get this error:
Too few positionals passed; expected 3 arguments but got 2
I don't even know where that error comes from. I think it's in cards_vars(), but I have no idea if that's the case or not. Declaring the macro without the parentheses yields the same error.
So a bit of poking about and I found this old halloween article : https://perl6advent.wordpress.com/2012/12/23/day-23-macros/
Which gives some pointer. You need to use
quasi
to highlight the code you're going to output. But getting it to create a variable? Not sure. I'm still setting if it's possible.Let's start with a golf of your code:
This yields the same compile-time error:
You get this error if you return anything other than an
AST
object from a macro. Which is reasonable given that this is the entire point of themacro
construct.1 The error message is less than awesome -- but then again macros are an experimental feature.So you need to return an AST. Here's one way:
This yields the run-time error:
This shows that the macro has done its job. The compiler has completed compilation and proceeded to run-time.
Explicitly returning
AST
objects is the wrong way to proceed. The first reason is given on theAST
doc page:The second reason is that there's a higher level construct for constructing
AST
objects, namely thequasi { ... }
construct3 mentioned on the doc page and by Scimon:The
quasi
block tells the compiler to compile the enclosed statements into AST form.Note that the result isn't an AST corresponding to a block. In the above it's an AST object corresponding to
42
.So, finally, back to what you were trying to do.
Simplifying:
yields:
Whereas:
So, bottom line, lexical declarations currently fail to stick.
The experiment hasn't gotten that far.
Carl Mäsak, the creator of the experimental macros in Rakudo, is continuing the experiment at 007. If you leave an issue at its GH repo Carl will answer.
1 When the compiler encounters a call to a routine that it knows is a macro2 it replaces the macro call with its result. In more detail the compiler:
Compiles all the macro's arguments into AST form;
Calls the macro (at compile-time) passing it the arguments in their AST form;
Runs the macro routine which is expected to return an AST object;
Splices the resulting AST object into the overall AST being constructed.
If you don't return an AST object the last step goes wrong with the error message in your title.
2 Currently, if you put the macro definition after the call then the compiler doesn't realize it's a macro and treats it as an ordinary routine:
It would presumably be better if this caused a compile-time error.
3 Carl, the macros champion, likes the word
quasi
. It draws from lisp heritage which draws from mathematics heritage. Imo it is a "too cute" choice that's a less than awesome fit for P6. My rationale is that Perl philosophy suggests choice of keywords with familiar meaning to newbies. The word "quasi" has a well known normal English connotation of meaning "sort of, but not really". That's not at all helpful. (I have suggestedtoAST
to Carl but he prefersquasi
.)