2010-09-13 18 views
18

Estoy trabajando en una pequeña DSL que utiliza la recuperación nomethod para sobrecargar para capturar los operadores utilizados en los valores sobrecargados. Esto es similar a la función del symbolic calculator que se describe en la documentación de overload.¿Hay alguna forma de sobrecargar el operador de vinculación de expresiones regulares `= ~` en Perl?

Esto funciona bien para los operadores de comparación estándar, pero tenga en cuenta lo siguiente:

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

En este caso, se llama a nomethod a stringify $overloaded, y después de que la sobrecarga se pierde. Pensé en devolver una variable atada, que al menos me permitiría transportar el objeto sobrecargado original, pero eso aún se perderá durante la ejecución de la expresión regular.

Por lo tanto, la última pregunta es si hay alguna manera de extender la idea de overload 's de una calculadora simbólica para incluir la operadores =~ y !~ vinculante expresiones regulares, de modo que el ejemplo de código anterior llamaría nomethod con ($overloaded, qr/regex/, 0, '=~') o algo similar?

También analicé brevemente la sobrecarga del operador de SmartChch ~~, pero eso tampoco pareció ser el truco (siempre se utiliza de forma predeterminada la coincidencia de expresiones regulares en lugar de la sobrecarga).

Editar: He buscado en ~~ más, y encontré que my $ret = $overloaded ~~ q/regex/ funciona debido a las reglas de Smartmatching. Cerrar, pero no es una solución ideal, y me gustaría que funcione antes de 5.10, así que agradezco otras respuestas.

+0

Supongo que el suministro de un contenedor al motor de expresiones regulares tampoco funcionaría si quiere que funcione antes de 5.10. –

+0

¡Termine con la locura! ¡Aprende Python! – bukzor

+0

@bukzor: estoy bastante seguro de que no se puede sobrecargar el operador de enlace regex en Python, ya que no tiene uno. Por supuesto, podría escribir una clase que le brinde una funcionalidad similar y limitada: http://code.activestate.com/recipes/302498-re-match-and-replace-through-operator-overloading/ –

Respuesta

2

Creo que las DSL se escriben mejor con source filters en perl. Usted puede literalmente hacer CUALQUIER COSA que desee. ;-) En su ejemplo, puede regex reemplazar FOO = ~ BAR con myfunc (FOO, BAR) y ejecutar código arbitrario.

He aquí un ejemplo de solución:

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

Ejemplo USO

use MyLang nomethod => \&mywrap; 

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

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

Ahora lo anterior imprimirá "foo \ n", ya que es lo que está en el "$ a" variable. Por supuesto, es posible que desee hacer un análisis ligeramente más inteligente para el reemplazo de expresiones regulares en el filtro, pero esta es una prueba de concepto simple.

+0

¿Por qué el voto a favor? –

+0

porque apesta en ping pong – mkoryak

+0

Probablemente porque, en general, los filtros fuente son una solución frágil, especialmente cuando el filtro tiene límites sensibles al contexto. Su ejemplo funciona en el caso de '$ x = $ a = ~ $ b', pero fallará con' $ x = myfunc $ a = ~ $ b'. Hay demasiados casos de esquina para que tales filtros fuente sean verdaderamente robustos. Además, si intenta escribir un filtro fuente, al menos debe usar 'Filter :: Simple' con el modificador' code_no_comments' para que solo filtre las áreas codificadas, y no los comentarios, pod o cadenas entre comillas. –

Cuestiones relacionadas