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

发布于 2024-09-18 14:44:46 字数 877 浏览 11 评论 0原文

我正在开发一个小型 DSL,它使用 nomethod 后备进行重载,以捕获用于重载值的运算符。这类似于overload<中描述的符号计算器的功能/code> 的文档。

这对于标准比较运算符来说效果很好,但请考虑以下情况:

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

在这种情况下,会调用 nomethod 来字符串化 $overloaded,之后重载就会丢失。我考虑过返回一个绑定变量,这至少可以让我携带原始的重载对象,但在正则表达式的执行过程中它仍然会丢失。

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

我还简要研究了重载 smartmatch 运算符 ~~ 但这似乎也没有解决问题(始终默认为正则表达式匹配而不是重载)。

编辑:我进一步研究了 ~~ ,发现 my $ret = $overloaded ~~ q/regex/ 由于智能匹配规则而有效。接近,但不是一个理想的解决方案,我希望它能在 5.10 之前工作,所以我欢迎其他答案。

I am working on a small DSL that uses the nomethod fallback for overloading to capture the operators used on the overloaded values. This is similar to the function of the symbolic calculator described in overload's documentation.

This works fine for the standard comparison operators, but consider the following:

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

In this case, nomethod gets called to stringify $overloaded, and after that the overloading is lost. I thought about returning a tied variable, which will at least let me carry around the original overloaded object, but that will still get lost during the execution of the regex.

So, the ultimate question is if there is any way to extend overload's idea of a symbolic calculator to include the regex binding operators =~ and !~, so that the above code sample would call nomethod with ($overloaded, qr/regex/, 0, '=~') or something similar?

I also briefly looked into overloading the smartmatch operator ~~ but that didn't seem to do the trick either (always defaults to regex matching rather than overloading).

Edit: I looked into ~~ more, and found that my $ret = $overloaded ~~ q/regex/ works due to smartmatching rules. Close, but not an ideal solution, and I would like it to work pre 5.10, so I welcome other answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

牵你的手,一向走下去 2024-09-25 14:44:46

我觉得 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;

示例使用

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

I feel as though DSLs are best written with source filters in perl. You can literally do ANYTHING you want. ;-) In your example, you can regex replace FOO =~ BAR with myfunc(FOO, BAR) and run arbitrary code.

Here's an example solution:

# 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;

EXAMPLE USE

use MyLang nomethod => \&mywrap;

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

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

Now the above will print "foo\n" since it's what is in the "$a" variable. Of course you may want to do some slightly more intelligent parsing for the regex replacement in the filter, but this is a simple proof of concept.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文