gpt4 book ai didi

macros - 宏定义中的"Too few positionals"

转载 作者:行者123 更新时间:2023-12-02 02:47:50 29 4
gpt4 key购买 nike

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

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

最佳答案

更新:需要明确的是,宏不仅是实验性的,而且非常初级且存在缺陷。有关此内容的更多信息,请参阅 Moritz's answer to another macros question .

<小时/>

让我们从代码开始:

use experimental :macros;
macro foo { 42 }
foo

这会产生相同的编译时错误:

Too few positionals passed; expected 3 arguments but got 2

如果您返回 AST 以外的任何内容,则会出现此错误来自宏的对象。1 这是合理的,因为这是构造的全部要点。错误消息不太好——但宏又是一个实验性功能。

<小时/>

所以你需要返回一个 AST。这是一种方法:

use experimental :macros;
macro foo { AST.new }
foo

这会产生运行时错误:

Useless use of constant value foo in sink context (line 3)

这表明宏已经完成了它的工作。编译器已完成编译并进入运行时。

<小时/>

显式返回 AST 对象是错误的处理方式。第一个原因在 AST 文档页面上给出:

There is no API defined for ASTs yet. Hopefully that will emerge as part of the work on macros.

第二个原因是有一个更高级别的构造用于构造 AST 对象,即提到的 quasi { ... } 构造3在文档页面上和 Scimon 提供:

use experimental :macros;
macro foo { quasi { 42 } }
say foo; # 42

quasi block 告诉编译器将所包含的语句编译为 AST 形式。

请注意,结果不是与 block 对应的 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)

所以,底线是,词法声明目前无法坚持下去。

实验还没有进行到那么远。

Carl Mäsak,Rakudo 中实验性宏的创建者,正在 007 继续进行实验。 。如果您在 GH 存储库中留下问题,Carl 将会回答。

<小时/>

1 当编译器遇到对它知道是宏的例程的调用时2,它会用其结果替换宏调用。更详细的编译器:

  • 将宏的所有参数编译为 AST 形式;

  • 调用宏(在编译时),以 AST 形式传递参数;

  • 运行预计返回 AST 对象的宏例程(呃, "ASTish" );

  • 将生成的 AST(ish) 对象拼接到正在构造的整体 AST 中。

如果您不返回 AST(ish) 对象,那么最后一步就会出错,并出现标题中的错误消息。

2 目前,如果您将宏定义放在调用之后,那么编译器不会意识到它是宏,并将其视为普通例程:

use experimental :macros;
say foo; # 42
macro foo { 42 }
say bar; # AST.new
macro bar { quasi { 42 } }
say bar; # 42

如果这会导致编译时错误,那可能会更好。

3 宏冠军 Carl 喜欢“quasi”这个词。它借鉴了 lisp 遗产,而 lisp 遗产又借鉴了数学遗产。在我看来,这是一个“太可爱”的选择,不太适合 P6。我的理由是 Perl 哲学建议新手选择具有熟悉含义的关键字。 “准”一词具有众所周知的正常英语含义,意思是“有点,但不是真的”。这根本没有帮助。 (我向 Carl 建议了 toAST,但他更喜欢 quasi。)

关于macros - 宏定义中的"Too few positionals",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53875026/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com