【发布时间】:2018-12-23 08:55:56
【问题描述】:
此代码使用(实验性)宏:
use experimental :macros;
macro new-var() {
quasi {
my $a = 42
}
};
new-var;
say $a
失败并显示Variable '$a' is not declared,尽管宏通过而没有错误。如果这是一个正确的宏声明,它会做什么?如果不是,有没有办法在宏中定义新变量?
【问题讨论】:
此代码使用(实验性)宏:
use experimental :macros;
macro new-var() {
quasi {
my $a = 42
}
};
new-var;
say $a
失败并显示Variable '$a' is not declared,尽管宏通过而没有错误。如果这是一个正确的宏声明,它会做什么?如果不是,有没有办法在宏中定义新变量?
【问题讨论】:
关于宏的状态,moritz 的回答是正确的,尽管根据我对 007 所做工作的了解,我认为即使使用 Perl 6 宏的有效实现,所编写的程序也不正确。
Perl 6 宏本质上不是文本的(C 宏是文本宏的一个示例)。 quasi 是一个引号结构,就像我们为字符串和正则表达式使用引号一样,只是它引用了 Perl 6 代码,将其表示为 AST-ish。 (我曾经说过它会产生 AST,但人们已经意识到,如果要在 quasi 中插入中缀,那么它具有优先级和关联性,我们实际上无法为直到插值后的表达式。)
有一个“卫生”的宏概念,默认情况下,宏体中声明的符号不应泄漏到应用宏的地方,因为它们很可能只是实现细节。必须明确要求将符号放入应用宏的编译上下文中。所以我希望程序看起来像这样:
macro new-var() {
quasi {
my COMPILING::<$a> = 42
}
};
new-var;
say $a
请注意,这在今天的 Rakudo 中无法使用,尽管您可能会发现类似的东西可以在 007 中使用。
【讨论】:
这可能不是您要寻找的答案,但 Rakudo 中的宏目前确实被破坏了。在这个时间点上,我什至不记得它是否应该工作,或者它是否是 Rakudo 中的一个错误 - 几乎不值得弄清楚,因为大多数宏观事情根本无法工作。
这就是 Carl Mäsak 创建 007 以在 Rakudo 核心之外试验宏设计的原因,目的是最终将学到的经验带回 Rakudo 和 Perl 6 语言设计。
【讨论】: