有没有办法在 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::Simplecode_no_comments 修饰符,以便您只过滤类似代码的区域,而不是 cmets、pod 或引用的字符串。 另外,一般情况下,您应该避免将变量 $a$b 词法化,因为一旦词法化,在该范围内对 sort 的任何调用都会终止。 所有这些都可能是真的,但他是唯一真正回答了这个问题的人。如果这样做的唯一方法是通过源过滤器,那将是有用的非格式化。不过,我承认它的主要用处在于,如果您只能使用源过滤器来做到这一点,也许您应该尝试简单地没有它。 ;) 顺便说一句,我不是投反对票的人,只是猜测为什么有人这样做

以上是关于有没有办法在 Perl 中重载正则表达式绑定运算符 `=~`?的主要内容,如果未能解决你的问题,请参考以下文章

Perl正则表达式选项存储在变量中[重复]

正则表达式中的 perl 正则表达式

在 perl 中解释正则表达式

寻找提示以更好地理解 Perl 兼容的正则表达式运算符和语法

类型匹配没有可行的重载运算符

Perl 正则表达式多行匹配没有点