2010-09-13 99 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