2010-09-13 101 views
18

我正在使用一个小的DSL,它使用nomethod回退来重载以捕获过载值上使用的运算符。这与overload的文档中描述的symbolic calculator的功能类似。有没有办法在Perl中重载正则表达式绑定运算符`=〜`?

这为标准比较操作工作正常,但考虑以下因素:

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

在这种情况下,nomethod去调用的字符串化$overloaded,并且超载丢失后。我想过要返回一个绑定变量,这个变量至少可以让我随身携带原来的重载对象,但在执行正则表达式时仍会丢失。

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

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

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

+0

我想提供一个包装到正则表达式引擎不会工作,如果你想在5.10之前工作。 – 2010-09-14 06:34:27

+0

结束疯狂!学习Python! – bukzor 2010-09-16 03:57:29

+0

@bukzor:我敢肯定,你不能在Python中重载正则表达式绑定操作符,因为它没有。当然,你可以编写一个类,给你类似的,有限的功能:http://code.activestate.com/recipes/302498-re-match-and-replace-through-operator-overloading/ – 2010-09-17 02:46:45

回答

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"; 
} 

现在,上面会打印出 “富\ n”,因为它就是在 “$ A” 的变量。当然,您可能想要为滤波器中的正则表达式替换做一些更智能的解析,但这是一个简单的概念验证。

+0

为什么downvote? – 2010-09-16 12:59:34

+0

,因为你在乒乓吸吮 – mkoryak 2010-09-16 14:06:13

+0

可能是因为一般来说,源过滤器是一个脆弱的解决方案,特别是当过滤器具有上下文敏感边界时。你的例子在'$ x = $ a =〜$ b'的情况下工作,但是会失败,并且$ x = myfunc $ a =〜$ b'。对于这样的源代码过滤器来说,有太多的角落案例需要真正的强大。另外,如果你试图编写一个源代码过滤器,你至少应该在'code_no_comments'修饰符中使用'Filter :: Simple',这样你只能过滤类似代码的区域,而不是注释,pod或带引号的字符串。 – 2010-09-16 17:46:28