这是我的宏:
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 '>'
我该如何解决?
解决方法
assert a ** 2 + b ** 2 == c ** 2;
这个断言语句宏可以评估它的表达式,如果失败,它可以打印出来.打印出来需要对其进行字符串化. (事实上,在这种情况下,拥有文件和行信息也会很好.)
(编辑:007是一个语言实验室,用于在Perl 6中充实宏.)
现在在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. (人们应该这样做.并将这些“合成Qtrees”与程序中的自然Qtrees混合在一起.)
所以我们正在看的是Q节点上的一个名为.source的属性.然后我们就能做到这一点:
$bin/007 -e='say((quasi { 2 + 2 }).source)' 2 + 2
(注意:还不行.)
这是一个有趣的问题.source应该输出合成Qtrees.它应该抛出异常吗?或者只输出<黑盒源>?或者尽最大努力将自己变成字符串化的来源?
回到原始代码,这条线让我着迷:
my $str = Q ({{{$expr}}});
它实际上是一个非常有说服力的尝试来表达你想要做的事情(将AST转换成它的字符串表示).但我怀疑它是否会按原样运作.最后,它仍然基于源代码作为字符串的C语言思想.它的基本问题是你放置{{{$expr}}}的地方(在字符串引用环境)不是表达式AST能够到达的地方.从AST节点类型的角度来看,它没有进行类型检查,因为表达式不是引用环境的子类型.
希望有所帮助!
(PS:退后一步,我认为你通过使filter-sub接受一个字符串参数来做你自己的伤害.你会对这个函数内部的字符串做什么?解析它以获取信息?在这种情况下你会最好分析AST,而不是字符串.)
(PPS:#perl6上的Moritz指出,年龄<50时存在一个不相关的语法错误需要解决.Perl 6在使用之前对于定义的东西很挑剔;宏不会更改这个等式.因此,Perl 6解析器将假设age是一个你尚未声明的函数.然后它会考虑<一个开头的引号字符.最后它会失望的是没有>.再次,宏不会拯救你不需要事先声明你的变量.(虽然参见#159进一步讨论.))