我希望在P6中创建一个宏,将其参数转换为字符串。下面是我的宏:
macro tfilter($expr) {
quasi {
my $str = Q ({{{$expr}}});
filter-sub $str;
};
}我是这样称呼它的:
my @some = tfilter(age < 50);然而,当我运行程序时,我得到了错误:
Unable to parse expression in quote words; couldn't find final '>'我该如何解决这个问题?
发布于 2017-04-27 15:15:53
您的用例--通过宏将一些代码转换为字符串--非常合理。尽管我遇到并思考过同样的用例,但还没有建立起这样的API (甚至在我的脑海中也是如此)。它在以下情况下会更好:
assert a ** 2 + b ** 2 == c ** 2;这个assert语句宏可以计算它的表达式,如果失败,它可以打印出来。打印出来需要将其串行化。(实际上,在这种情况下,拥有文件和行信息也是不错的选择。)
(编辑:007是一个语言实验室,用于充实Perl6中的宏。)
现在在007中,如果你字符串一个Q对象(一个AST),你得到的是AST本身的压缩对象表示,而不是它所表示的代码:
$ bin/007 -e='say(~quasi { 2 + 2 })'
Q::Infix::Addition {
identifier: Q::Identifier "infix:+",
lhs: Q::Literal::Int 2,
rhs: Q::Literal::Int 2
}这可能比输出源代码更有意义、更直接。还要考虑这样一个事实,即构建从一开始就不是源代码的AST是可能的。(预计人们会这样做。并将这种“合成Qtree”与程序中的自然Qtree混合。)
所以也许我们看到的是Q节点上的一个叫做.source的属性或者别的什么。然后我们就可以这样做了:
$ bin/007 -e='say((quasi { 2 + 2 }).source)'
2 + 2 (注意:目前还不起作用。)
这是一个有趣的问题,.source应该为合成Qtree输出什么。它应该抛出一个异常吗?或者只是输出<black box source>?或者尽最大努力将自己转变为stringified源代码?
回到您的原始代码,这一行让我着迷:
my $str = Q ({{{$expr}}});这实际上是一种非常有说服力的尝试来表达您想要做的事情(将AST转换为它的字符串表示)。但我怀疑它永远不会按原样工作。最后,它仍然是一种类似于C的源代码即字符串的思维方式。它的根本问题是,您放置{{{$expr}}}的地方(在字符串引用环境中)并不是表达式AST能够到达的地方。从AST节点类型的角度来看,它不会检查类型,因为表达式不是引用环境的子类型。
希望这能有所帮助!
(PS:后退一步,我认为让filter-sub接受字符串参数是在伤害自己。您将如何处理此函数中的字符串?解析它以获取信息?在这种情况下,最好分析AST,而不是字符串。)
(PPS:#perl6上的Moritz++指出,age < 50中存在一个需要解决的不相关的语法错误。Perl6对在使用之前定义的东西很挑剔;宏不会对这个等式有太大的改变。因此,Perl6解析器将假定age是一个尚未声明的函数。然后,它将把<视为开始引号字符。最终,它会对没有>感到失望。同样,宏也不能帮助您避免预先声明变量的需要。(有关详细讨论,请参阅#159。)
https://stackoverflow.com/questions/43561614
复制相似问题