2010-09-13 25 views
18

Je travaille sur un petit DSL qui utilise le fallback nomethod pour surcharger afin de capturer les opérateurs utilisés sur les valeurs surchargées. Ceci est similaire à la fonction de symbolic calculator décrite dans la documentation overload.Existe-t-il un moyen de surcharger l'opérateur de liaison de regex `= ~` en Perl?

Cela fonctionne très bien pour les opérateurs de comparaison standard, mais considérer les points suivants:

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

Dans ce cas, nomethod est appelé à stringify $overloaded, et après que la surcharge est perdue. J'ai pensé renvoyer une variable attachée, ce qui me permettra au moins de contourner l'objet surchargé original, mais cela sera encore perdu pendant l'exécution de l'expression rationnelle.

Ainsi, la question ultime est de savoir s'il y a un moyen d'étendre l'idée de » overload d'une calculatrice symbolique pour inclure les opérateurs de liaison regex =~ et !~, de sorte que l'échantillon de code ci-dessus appellerait nomethod avec ($overloaded, qr/regex/, 0, '=~') ou quelque chose de similaire?

J'ai également brièvement examiné la surcharge de l'opérateur smartmatch ~~ mais cela ne semble pas non plus faire l'affaire (toujours par défaut pour l'appariement d'expressions rationnelles plutôt que de surcharges).

Modifier: J'ai regardé dans ~~ plus, et a constaté que my $ret = $overloaded ~~ q/regex/ fonctionne en raison de règles smartmatching. Fermer, mais ce n'est pas une solution idéale, et j'aimerais que cela fonctionne avant le 5.10, alors j'accueille d'autres réponses.

+0

Je suppose que la fourniture d'un wrapper au moteur regex ne fonctionnerait pas non plus si vous voulez que cela fonctionne avant 5.10. –

+0

Fin de la folie! Apprenez Python! – bukzor

+0

@bukzor: Je suis sûr que vous ne pouvez pas surcharger l'opérateur de liaison de regex en Python, car il n'en a pas. Bien sûr, vous pourriez écrire une classe qui vous donnerait des fonctionnalités similaires, limitées: http://code.activestate.com/recipes/302498-re-match-and-replace-through-operator-overloading/ –

Répondre

2

Je me sens comme si les DSL sont mieux écrits avec source filters en perl. Vous pouvez littéralement faire tout ce que vous voulez. ;-) Dans votre exemple, vous pouvez regex remplacer FOO = ~ BAR avec myfunc (FOO, BAR) et exécuter du code arbitraire.

Voici un exemple de 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; 

EXEMPLE DE L'UTILISATION

use MyLang nomethod => \&mywrap; 

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

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

Maintenant, la imprimera ci-dessus "foo \ n", car il est ce qui est dans le "$ a" variable. Bien sûr, vous voudrez peut-être faire un peu plus d'analyse intelligente pour le remplacement de regex dans le filtre, mais ceci est une simple preuve de concept.

+0

Pourquoi la downvote? –

+0

parce que vous aspirez à ping-pong – mkoryak

+0

Probablement parce qu'en général, les filtres de source sont une solution fragile, particulièrement quand le filtre a des limites contextuelles. Votre exemple fonctionne dans le cas de '$ x = $ a = ~ $ b', mais échouera avec' $ x = myfunc $ a = ~ $ b'. Il y a juste trop de casse-tête pour que ces filtres soient vraiment robustes. En outre, si vous essayez d'écrire un filtre source, vous devez au moins utiliser Filter: Simple avec le modificateur codec_code_no pour que vous ne filtriez que les zones codées, et non pas les commentaires, les pods ou les chaînes entre guillemets. –