宏定义中的“位置太少”

时间:2018-12-20 19:40:18

标签: macros perl6

我正在尝试通过这种方式创建一些使用(实验性)宏的示例:

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()中,但我不知道是否是这种情况。声明不带括号的宏会产生相同的错误。

2 个答案:

答案 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突出显示要输出的代码。但是让它创建一个变量吗?不确定。如果可能,我仍在设置。