我试图用这种方式创建一些使用(实验)宏的例子:
use experimental :macros;
macro cards_vars() {
(<hearts clubs diamonds spades> X~ 1..10).map: { "my \$$^x = False;" }
};
cards_vars();
say $hearts1;
Run Code Online (Sandbox Code Playgroud)
这将创建并运行宏,然后检查是否存在已定义的变量之一.但我得到这个错误:
Too few positionals passed; expected 3 arguments but got 2
Run Code Online (Sandbox Code Playgroud)
我甚至不知道那个错误来自哪里.我认为它在cards_vars()中,但我不知道是否是这种情况.声明没有括号的宏会产生相同的错误.
让我们从您的代码高尔夫开始:
use experimental :macros;
macro foo { 42 }
foo
Run Code Online (Sandbox Code Playgroud)
这会产生相同的编译时错误:
Too few positionals passed; expected 3 arguments but got 2
Run Code Online (Sandbox Code Playgroud)
如果AST从宏返回除对象之外的任何内容,则会出现此错误.鉴于这是macro构造的全部要点,这是合理的.1错误消息不是很棒 - 但是再次宏是一个实验性功能.
所以你需要返回一个AST.这是一种方式:
use experimental :macros;
macro foo { AST.new }
foo
Run Code Online (Sandbox Code Playgroud)
这会产生运行时错误:
Useless use of constant value foo in sink context (line 3)
Run Code Online (Sandbox Code Playgroud)
这表明宏已经完成了它的工作.编译器已完成编译并继续运行.
显式返回AST对象是错误的继续进行方式.第一个原因在ASTdoc页面上给出:
尚未为AST定义API.希望这将成为宏工作的一部分.
第二个原因是有一个更高级别的构造用于构造AST对象,即在doc页面和Scimon上提到的quasi { ... }构造3:
use experimental :macros;
macro foo { quasi { 42 } }
say foo; # 42
Run Code Online (Sandbox Code Playgroud)
该quasi块告诉编译器将所包含的语句编译为AST形式.
注意,结果不是对应于块的AST.在上面它是一个对应的AST对象42.
所以,最后,回到你想要做的事情.
简化:
use experimental :macros;
macro foo { quasi { my $bar } }
foo;
say $bar
Run Code Online (Sandbox Code Playgroud)
收益率:
Error while compiling ... Variable '$bar' is not declared
Run Code Online (Sandbox Code Playgroud)
鉴于:
use experimental :macros;
macro foo { quasi { class bar {} } }
foo;
say bar; # (bar)
Run Code Online (Sandbox Code Playgroud)
因此,底线,词汇声明目前未能成功.
实验还没有那么远.
Rakudo实验宏的创建者CarlMäsak将在007继续进行实验.如果你在GH回购中留下问题,Carl会回答.
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
Run Code Online (Sandbox Code Playgroud)
如果这会导致编译时错误,那么可能会更好.
3卡尔,宏冠军,喜欢这个词quasi.它吸取了来自数学遗产的lisp遗产.Imo这是一个"太可爱"的选择,它不太适合P6.我的理由是,Perl哲学建议选择具有新手熟悉意义的关键词."准"这个词有一个众所周知的正常英语含义,意思是"有点,但不是真的".这根本没用.(我建议toAST卡尔,但他更喜欢quasi.)
所以有点戳,我找到了这个古老的万圣节文章:https://perl6advent.wordpress.com/2012/12/23/day-23-macros/
这给了一些指针.您需要使用quasi突出显示要输出的代码.但是让它创建一个变量?不确定.如果可能的话,我还在设定.
| 归档时间: |
|
| 查看次数: |
92 次 |
| 最近记录: |