Hacer un declarador personalizado


9

Digamos que uso cierto conjunto de repeticiones con bastante frecuencia:

class Foo {

  method abc($a: $b, $c, +@d) is pure {
    use Slang::Bar;
    …
  }

  method xyz($a: $b, $c, +@d) is pure {
    use Slang::Bar;
    …
  }

  method blarg($a: $b, $c, +@d) is pure {
    use Slang::Bar;
    …
  }

}

Prefiero poder decir:

class Foo is/does Bar {
  bar  abc   { … }
  bar  xyz   { … }
  bar  blarg { … }
}

Y en algún lugar de Bar, configure la declaración para bar (o, dado que la clase Foo finalmente usará su propio declarador, podría ir a otro lugar y no tiene que extraerse en un Tipo separado). ¿Cómo voy a hacer eso?


Entiendo que esto básicamente es preguntar "¿Cómo lo hago?" pero no he visto ninguna crítica real, y los módulos existentes que lo usan (Red / Cro) son bestias bastante complejas (aunque hermosas) que son difíciles de seguir de un vistazo.
user0721090601

Parece que quieres reutilizar las firmas, ¿verdad?
jjmerelo

2
jjmerelo: no, en realidad el objetivo final es hacer una subclase de método (registrándola con la clase si se usa dentro de ella) y usando un lenguaje completamente diferente dentro del bloque de código (uno similar a la expresión regular, en este caso)
user0721090601

2
jjmerelo: ver gist.github.com/alabamenhu/2fec7a8f51a24091dc1b104a2ae2f04d para la propuesta. Me faltan unos días para mostrar un módulo de prueba, pero tengo la mayor parte de la logística del Binex funcionando, pero para la sintaxis similar a Raku
user0721090601

Respuestas:


5

-1. Limitaciones (solo para paquetes)

El método EXPORTHOW llama a .set_how en current $?LANGagregando un argot a este último.
Luego agrega el paquete_declarador al MAIN $?LANGque agrega un package_declaratormétodo a sus acciones y gramática. Es, creo, la única "jerga dinámica" (en World.nqp).

Si lo que desea es sobrescribir rutina_declarador . Luego tienes que escribir una jerga que imite la cadena que acabamos de citar. Si acepta mantener la palabra clave del método y hacer la firma automática en la clase, digamos de acuerdo con el nombre del método, esta es una manera:

Nota: Un paquete es un contenedor (paquete, gramática, módulo, rol, knowhow, enumeración, clase, subconjunto). Si pones código dentro como un método, esto se ejecuta (lo acabo de probar):

0. Descripción (EXPORTHOW)

Usaría EXPORTHOW indocumentado y DECLAREen un módulo porque no encontré una manera con Phaser . Aparentemente es demasiado tarde incluso en BEGIN.

El ejemplo que doy es decorar cada método en una clase (incluso BUILDALL).

1. Lib ( decorator.rakumod)

class DecoratedClassHOW is Metamodel::ClassHOW {
    method add_method(Mu $obj, $name, $code_obj) {
        sub wrapper ($obj, $a, $b) {
            say "Before $name";
            my $res = $code_obj($obj, $a, $b);
            say "After $name";
            return $res;
        }
        my $res = callwith($obj, $name, &wrapper);
        return $res;
    }
}

my module EXPORTHOW {
    package DECLARE {
        constant decorated = DecoratedClassHOW;
    }
}

2. Ejecutable

use lib '.';
use decorator-lib;

decorated Foo {
  method abc($a, $b) {
      say "In abc: $a:$b";
  }
}

my $f = Foo.new;
$f.abc(1, 2);

3. Salida

Before BUILDALL
After BUILDALL
Before abc
In abc: 1:2
After abc

4. Fuentes


Excelente. Simple y directo. ¡Gracias!
user0721090601
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.