有没有办法在 Perl 中重载正则表达式绑定运算符 `=~`?
Posted
技术标签:
【中文标题】有没有办法在 Perl 中重载正则表达式绑定运算符 `=~`?【英文标题】:Is there a way to overload the regex binding operator `=~` in Perl? 【发布时间】:2011-04-11 22:02:32 【问题描述】:我正在开发一个小型 DSL,它使用 nomethod
回退进行重载,以捕获用于重载值的运算符。这类似于overload
的文档中描述的symbolic calculator 的功能。
这适用于标准比较运算符,但请考虑以下几点:
my $ret = $overloaded =~ /regex/;
在这种情况下,调用nomethod
对$overloaded
进行字符串化,然后重载丢失。我考虑过返回一个绑定变量,这至少可以让我携带原始重载对象,但在执行正则表达式期间仍然会丢失。
所以,最终的问题是,是否有任何方法可以扩展overload
的符号计算器概念,使其包含正则表达式绑定运算符=~
和!~
,以便上述代码示例调用@987654331 @ 和 ($overloaded, qr/regex/, 0, '=~')
或类似的东西?
我还简要研究了重载 smartmatch 运算符 ~~
但这似乎也没有解决问题(始终默认为正则表达式匹配而不是重载)。
编辑:我查看了~~
更多,发现my $ret = $overloaded ~~ q/regex/
由于智能匹配规则而起作用。关闭,但不是一个理想的解决方案,我希望它在 5.10 之前工作,所以我欢迎其他答案。
【问题讨论】:
我想如果你想让它在 5.10 之前工作,那么为正则表达式引擎提供一个包装器也行不通。 结束疯狂!学习 Python! @bukzor:我很确定您不能在 Python 中重载正则表达式绑定运算符,因为它没有。当然,你可以编写一个类来提供类似的、有限的功能:code.activestate.com/recipes/… @Adam => 当然同样可以在 perl 中完成。我一直在考虑让$overloaded == qr/.../
的通常毫无意义的情况与$overloaded =~ /.../
的行为方式相同。至少可以在 5.10 之前使用...
【参考方案1】:
我觉得 DSL 最好用 perl 中的source filters 编写。你可以从字面上做任何你想做的事情。 ;-) 在您的示例中,您可以正则表达式将 FOO =~ BAR 替换为 myfunc(FOO, BAR) 并运行任意代码。
这是一个示例解决方案:
# THE "MyLang" SOURCE FILTER
package MyLang;
use strict;
use warnings;
use Filter::Util::Call;
sub import
my ($type, @args) = @_;
my %p = @args;
no strict 'refs';
my $caller = caller;
# Create the function to call
*"$caller::_mylang_defaultmethod" = sub
my ($a, $op, $b) = @_;
$pnomethod->($a, $b, 0, $op);
;
my ($ref) = [];
filter_add(bless $ref);
sub filter
my ($self) = @_;
my ($status);
if ($status = filter_read() > 0)
$_ =~ s/([^=]+)(=~)([^;]+)/ _mylang_defaultmethod($1,'$2',$3)/g;
$status;
1;
使用示例
use MyLang nomethod => \&mywrap;
my $a = "foo";
my $b = "bar";
$x = $a =~ $b;
sub mywrap
my ($a, $b, $inv, $op) = @_;
print "$a\n";
现在上面将打印“foo\n”,因为它是“$a”变量中的内容。当然,您可能希望对过滤器中的正则表达式替换做一些更智能的解析,但这是一个简单的概念证明。
【讨论】:
因为你乒乓球很烂 可能是因为一般来说,源过滤器是一个脆弱的解决方案,尤其是当过滤器具有上下文敏感边界时。您的示例适用于$x = $a =~ $b
,但会因$x = myfunc $a =~ $b
而失败。对于这样的源过滤器来说,有太多的极端情况要真正健壮。此外,如果您确实尝试编写源过滤器,您至少应该使用 Filter::Simple
和 code_no_comments
修饰符,以便您只过滤类似代码的区域,而不是 cmets、pod 或引用的字符串。
另外,一般情况下,您应该避免将变量 $a
和 $b
词法化,因为一旦词法化,在该范围内对 sort
的任何调用都会终止。
所有这些都可能是真的,但他是唯一真正回答了这个问题的人。如果这样做的唯一方法是通过源过滤器,那将是有用的非格式化。不过,我承认它的主要用处在于,如果您只能使用源过滤器来做到这一点,也许您应该尝试简单地没有它。 ;)
顺便说一句,我不是投反对票的人,只是猜测为什么有人这样做以上是关于有没有办法在 Perl 中重载正则表达式绑定运算符 `=~`?的主要内容,如果未能解决你的问题,请参考以下文章