【问题标题】:Is there a way to overload the regex binding operator `=~` in Perl?有没有办法在 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 之前使用...

标签: regex perl operator-overloading overloading


【解决方案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) = @_;
        $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”变量中的内容。当然,您可能希望对过滤器中的正则表达式替换做一些更智能的解析,但这是一个简单的概念证明。

【讨论】:

  • 因为你乒乓球很烂
  • 可能是因为一般来说,源过滤器是一个脆弱的解决方案,尤其是当过滤器具有上下文敏感边界时。您的示例适用于$x = $a =~ $b,但会因$x = myfunc $a =~ $b 而失败。对于这样的源过滤器来说,有太多的极端情况要真正健壮。此外,如果您确实尝试编写源过滤器,您至少应该使用 Filter::Simplecode_no_comments 修饰符,以便您只过滤类似代码的区域,而不是 cmets、pod 或引用的字符串。
  • 另外,一般情况下,您应该避免将变量 $a$b 词法化,因为一旦词法化,在该范围内对 sort 的任何调用都会终止。
  • 所有这些都可能是真的,但他是唯一真正回答了这个问题的人。如果这样做的唯一方法是通过源过滤器,那将是有用的非格式化。不过,我承认它的主要用处在于,如果您只能使用源过滤器来做到这一点,也许您应该尝试简单地没有它。 ;)
  • 顺便说一句,我不是投反对票的人,只是猜测为什么有人这样做
猜你喜欢
  • 2010-10-31
  • 2013-02-26
  • 2020-06-19
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
相关资源
最近更新 更多