Update:需要明确的是,宏不仅是实验性的,而且非常初级且有缺陷。有关此内容的更多信息,请参阅莫里茨对另一个宏问题的回答 https://stackoverflow.com/a/53902789/1077672.
让我们从代码开始:
use experimental :macros;
macro foo { 42 }
foo
这产生相同的编译时 error:
Too few positionals passed; expected 3 arguments but got 2
You get this error if you return anything other than an AST https://docs.perl6.org/type/AST object from a macro.1 Which is reasonable given that this is the entire point of the macro
construct. The error message is less than awesome -- but then again macros are an experimental feature.
所以你需要返回一个 AST。这是一种方法:
use experimental :macros;
macro foo { AST.new }
foo
这产生了run-time error:
Useless use of constant value foo in sink context (line 3)
这表明宏已经完成了它的工作。编译器已完成编译并进入运行时。
明确返回AST
对象是错误的处理方式。第一个原因是在AST
文档页面:
目前还没有为 AST 定义 API。希望这将成为宏的工作 https://github.com/masak/007.
The second reason is that there's a higher level construct for constructing AST
objects, namely the quasi { ... }
construct3 mentioned on the doc page and by Scimon:
use experimental :macros;
macro foo { quasi { 42 } }
say foo; # 42
The quasi
block 告诉编译器将所包含的语句编译为 AST 形式。
请注意,结果不是与块对应的 AST。上面它是一个 AST 对象,对应于42
.
所以,最后,回到你想要做的事情。
简化:
use experimental :macros;
macro foo { quasi { my $bar } }
foo;
say $bar
yields:
Error while compiling ... Variable '$bar' is not declared
Whereas:
use experimental :macros;
macro foo { quasi { class bar {} } }
foo;
say bar; # (bar)
因此,最重要的是,词法声明目前无法坚持下去。
实验还没有进行到这一步。
Carl Mäsak,Rakudo 中实验宏的创建者,正在继续进行该实验007 https://github.com/masak/007。如果您在 GH 存储库中留下问题,Carl 将会答复。
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:
如果您不返回 AST(ish) 对象,那么最后一步就会出错,并出现标题中的错误消息。
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:
use experimental :macros;
say foo; # 42
macro foo { 42 }
say bar; # AST.new
macro bar { quasi { 42 } }
say bar; # 42
如果这会导致编译时错误,那可能会更好。
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 suggested toAST
to Carl but he prefers quasi
.)