我正在尝试通过这种方式创建一些使用(实验性)宏的示例:
use experimental :macros;
macro cards_vars() {
(<hearts clubs diamonds spades> X~ 1..10).map: { "my \$$^x = False;" }
};
cards_vars();
say $hearts1;
这将创建并运行宏,然后检查定义的变量之一是否存在。但是我得到这个错误:
Too few positionals passed; expected 3 arguments but got 2
我什至不知道该错误来自何处。我认为它在cards_vars()中,但我不知道是否是这种情况。声明不带括号的宏会产生相同的错误。
答案 0 :(得分:6)
让我们从打入代码开始吧:
use experimental :macros;
macro foo { 42 }
foo
这会产生相同的编译时错误:
Too few positionals passed; expected 3 arguments but got 2
如果从宏返回AST
对象以外的任何内容,则会出现此错误。鉴于这是macro
构造的全部要点,这是合理的。 1 错误消息虽然不那么令人敬畏-但是宏仍然是实验性功能。
因此您需要返回AST。这是一种方法:
use experimental :macros;
macro foo { AST.new }
foo
这会产生运行时错误:
Useless use of constant value foo in sink context (line 3)
这表明宏已完成其工作。编译器已完成编译并进入运行时。
显式返回AST
对象是错误的处理方式。第一个原因在AST
文档页面上给出:
尚无为AST定义的API。希望这会成为the work on macros的一部分。
第二个原因是,存在用于构建AST
对象的更高级别的构造,即doc页面和Scimon提到的quasi { ... }
构造 3 :
use experimental :macros;
macro foo { quasi { 42 } }
say foo; # 42
quasi
块告诉编译器将随附的语句编译为AST形式。
请注意,结果不是与块相对应的AST。在上面,它是一个与42
对应的AST对象。
所以,最后,回到您想做的事情。
简化:
use experimental :macros;
macro foo { quasi { my $bar } }
foo;
say $bar
产量:
Error while compiling ... Variable '$bar' is not declared
位置:
use experimental :macros;
macro foo { quasi { class bar {} } }
foo;
say bar; # (bar)
因此,最重要的是,词汇表声明当前无法粘贴。
实验还没有完成。
Rakudo中的实验宏的创建者CarlMäsak正在007继续进行实验。如果您在GH仓库中遇到问题,卡尔会回答。
1 当编译器遇到对它知道是宏 2 的例程的调用时,它将用其结果替换该宏调用。更详细的是编译器:
将宏的所有参数编译为AST形式;
调用宏(在编译时),以其AST形式为其传递参数;
运行应返回AST对象的宏例程;
将生成的AST对象拼接到正在构建的整个AST中。
如果您不返回AST对象,则最后一步会出错,标题中会显示错误消息。
2 当前,如果在调用之后放置宏定义 ,则编译器不会意识到它是一个宏并将其视为普通例程:
use experimental :macros;
say foo; # 42
macro foo { 42 }
say bar; # AST.new
macro bar { quasi { 42 } }
say bar; # 42
如果这会导致编译时错误,那就更好了。
3 宏冠军Carl喜欢quasi
一词。它取材于口齿不清的遗产,后者取材于数学遗产。 Imo这是一个“太可爱了”的选择,对于P6来说它真是太棒了。我的理由是,Perl哲学建议对新手具有熟悉意义的关键字进行选择。 “准”一词具有众所周知的普通英语含义,意思是“有点,但不是真的”。那根本没有帮助。 (我向卡尔建议toAST
,但他更喜欢quasi
。)
答案 1 :(得分:5)
好一会儿,我发现了这篇古老的万圣节文章:https://perl6advent.wordpress.com/2012/12/23/day-23-macros/
哪个给出一些指针。您需要使用quasi
突出显示要输出的代码。但是让它创建一个变量吗?不确定。如果可能,我仍在设置。