有没有办法在Perl中重载正则表达式绑定运算符`= ~`?

Eri*_*rom 18 regex perl overloading operator-overloading

我正在研究一个小型DSL,它使用nomethod回退进行重载来捕获重载值上使用的运算符.这类似于文档中描述的符号计算器的功能overload.

这适用于标准比较运算符,但请考虑以下事项:

my $ret = $overloaded =~ /regex/;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,nomethod调用stringify $overloaded,之后失去重载.我想要返回一个绑定变量,这至少会让我随身携带原始的重载对象,但在执行正则表达式时仍会丢失.

所以,最终的问题是,如果有什么办法可以延长overload的一个象征性的计算器的主意,包括正则表达式结合运营商=~!~,使上面的代码示例将调用nomethod($overloaded, qr/regex/, 0, '=~')或类似的东西?

我还简要介绍了重载smartmatch运算符,~~但似乎也没有做到这一点(总是默认为正则表达式匹配而不是重载).

编辑:我调查了~~更多,并发现my $ret = $overloaded ~~ q/regex/由于智能匹配规则的作用.关闭,但不是一个理想的解决方案,我希望它在5.10之前工作,所以我欢迎其他答案.

Mik*_*iak 3

我觉得 DSL 最好用Perl 中的源过滤器编写。你确实可以做任何你想做的事。;-) 在您的示例中,您可以使用正则表达式将 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) = @_;
        $p{nomethod}->($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;
Run Code Online (Sandbox Code Playgroud)

使用示例

use MyLang nomethod => \&mywrap;

my $a = "foo";
my $b = "bar";
$x = $a =~ $b;

sub mywrap {
   my ($a, $b, $inv, $op) = @_;
   print "$a\n";
}
Run Code Online (Sandbox Code Playgroud)

现在上面将打印“foo\n”,因为它是“$a”变量中的内容。当然,您可能想要对过滤器中的正则表达式替换进行一些稍微更智能的解析,但这是一个简单的概念证明。