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

时间:2010-09-13 22:28:24

标签: regex perl operator-overloading overloading

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

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

my $ret = $overloaded =~ /regex/;

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

所以,最终的问题是,是否有任何方法可以扩展overload的符号计算器的概念,以包含正则表达式绑定运算符=~!~,以便上述代码示例会使用nomethod或类似内容调用($overloaded, qr/regex/, 0, '=~')吗?

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

修改:我进一步调查~~,发现my $ret = $overloaded ~~ q/regex/因智能匹配规则而有效。关闭,但不是一个理想的解决方案,我希望它在5.10之前工作,所以我欢迎其他答案。

1 个答案:

答案 0 :(得分:2)

我觉得在perl中使用source filters编写最好的DSL。你可以从字面上做你想要的任何事情。 ;-)在你的例子中,你可以用myfunc(FOO,BAR)替换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;

示例使用

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”变量中的内容。当然,您可能希望对过滤器中的正则表达式替换进行一些稍微更智能的解析,但这是一个简单的概念证明。