Creare un dichiaratore personalizzato


9

Diciamo che uso un certo set di boilerplate abbastanza regolarmente:

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

}

Preferirei solo poter dire:

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

E da qualche parte in Bar, imposta la dichiarazione per bar (o, dal momento che la classe Foo stessa userà il proprio dichiaratore, potrebbe andare da qualche altra parte e non deve essere estratta in un Tipo separato). Come potrei farlo?


Capisco che questo sostanzialmente sta chiedendo "Come posso COME?" ma non ho visto alcun vero write up, e i moduli esistenti che lo usano (Red / Cro) sono bestie abbastanza complesse (se belle) che sono difficili da seguire a colpo d'occhio.
user0721090601

Sembra che tu voglia riutilizzare le firme, giusto?
jjmerelo,

2
jjmerelo: no, in realtà l'obiettivo finale è quello di fare una sottoclasse di metodo (registrandola con la classe se usata al suo interno) e usando una lingua completamente diversa all'interno del blocco di codice (una di tipo regex, in questo caso)
user0721090601

2
jjmerelo: vedi gist.github.com/alabamenhu/2fec7a8f51a24091dc1b104a2ae2f04d per la proposta. Sono a pochi giorni dall'avere un modulo di test da mostrare, ma ho la maggior parte della logistica del Binex funzionante, ma per la sintassi simile a Raku
user0721090601

Risposte:


5

-1. Limitazioni (solo per i pacchetti)

Il metodo EXPORTHOW chiama .set_how al momento $?LANGaggiungendo un gergo a quest'ultimo.
Quindi aggiunge_package_declarator al MAIN $?LANGquale aggiunge un package_declaratormetodo alle sue azioni e grammatica. È, credo, l'unico "gergo dinamico" (in World.nqp).

Se quello che vuoi è sovrascrivere routine_declarator . Quindi devi scrivere un gergo che imita la catena appena citata. Se accetti di mantenere la parola chiave del metodo e fai la firma automatica nella classe, ad esempio in base al nome del metodo, ecco un modo:

Nota: un pacchetto è un contenitore (pacchetto, grammatica, modulo, ruolo, know-how, enum, classe, sottoinsieme). Se inserisci il codice come un metodo, questo viene eseguito (l'ho appena provato):

0. Descrizione (EXPORTHOW)

Userei EXPORTHOW non documentato e DECLAREin un modulo perché non ho trovato un modo con Phaser . Apparentemente è troppo tardi anche a BEGIN.

L'esempio che do, è decorare ogni metodo in una classe (anche 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. eseguibile

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. Uscita

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

4. Fonti


Eccellente. Semplice e diretto. Grazie!
user0721090601
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.