Faire un déclarant personnalisé

9

Disons que j'utilise un certain ensemble de passe-partout assez régulièrement:

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

}

Je préfère pouvoir simplement dire:

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

Et quelque part dans Bar, configurez la déclaration pour bar (ou, puisque la classe Foo utilisera elle-même finalement son propre déclarant, elle pourrait aller ailleurs et n'a pas besoin d'être extraite dans un type séparé). Comment pourrais-je procéder?

user0721090601
la source
Je comprends que cela demande essentiellement "Comment puis-je COMMENT?" mais je n'ai vu aucune véritable écriture, et les modules existants qui l'utilisent (Red / Cro) sont des bêtes assez complexes (si belles) qui sont difficiles à suivre en un coup d'œil.
user0721090601
Il semble que vous souhaitiez réutiliser les signatures, non?
jjmerelo
2
jjmerelo: non, le but ultime est de faire une sous-classe de méthode (en l'enregistrant avec la classe si elle est utilisée à l'intérieur) et en utilisant un langage entièrement différent à l'intérieur du bloc de code (un style regex, dans ce cas)
user0721090601
2
jjmerelo: voir gist.github.com/alabamenhu/2fec7a8f51a24091dc1b104a2ae2f04d pour la proposition. Je ne suis qu'à quelques jours d'avoir un module de test à montrer, mais j'ai la majeure partie de la logistique du Binex, mais pour la syntaxe Raku
user0721090601

Réponses:

5

-1. Limitations (uniquement pour les packages)

La méthode EXPORTHOW appelle .set_how sur le courant en $?LANGajoutant un argot à ce dernier.
Ensuite, il ajoute add_package_declarator au MAIN $?LANGqui ajoute une package_declaratorméthode à ses actions et à sa grammaire. C'est, je pense, le seul "argot dynamique" (dans World.nqp).

Si vous voulez écraser routine_declarator . Ensuite, vous devez écrire un argot imitant la chaîne que je viens de citer. Si vous acceptez de conserver le mot-clé method et de faire la signature automatique dans la classe, disons selon le nom de la méthode, voici un moyen:

Remarque: Un package est un conteneur (package, grammaire, module, rôle, savoir-faire, énumération, classe, sous-ensemble). Si vous mettez du code à l'intérieur comme une méthode, cela s'exécute (je viens de l'essayer):

0. Description (EXPORTATION)

J'utiliserais EXPORTHOW non documenté et DECLAREdans un module car je n'ai pas trouvé de moyen avec Phaser . Apparemment, il est trop tard, même à BEGIN.

L'exemple que je donne est de décorer chaque méthode d'une classe (même 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. Exécutable

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

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

4. Sources

Tinmarino
la source
Excellent. Simple et direct. Merci!
user0721090601