Erstellen eines benutzerdefinierten Deklarators


9

Nehmen wir an, ich benutze ziemlich regelmäßig einen bestimmten Satz Boilerplate:

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

}

Ich möchte lieber einfach sagen:

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

Und irgendwo in Bar richten Sie die Deklaration für bar ein (oder, da die Klasse Foo letztendlich selbst einen eigenen Deklarator verwendet, könnte sie woanders hingehen und muss nicht in einem separaten Typ herausgezogen werden). Wie würde ich das machen?


Ich verstehe, dass dies im Grunde die Frage "Wie gehe ich wie?" Aber ich habe keine wirklichen Aufzeichnungen gesehen, und die vorhandenen Module, die es verwenden (Rot / Cro), sind ziemlich komplexe (wenn auch schöne) Bestien, denen man auf einen Blick nur schwer folgen kann.
user0721090601

Es sieht so aus, als ob Sie Signaturen wiederverwenden möchten, oder?
jjmerelo

2
jjmerelo: nein, das ultimative Ziel ist es, eine Methodenunterklasse zu erstellen (sie bei der Klasse zu registrieren, wenn sie darin verwendet wird) und eine völlig andere Sprache innerhalb des Codeblocks zu verwenden (in diesem Fall eine Regex-ähnliche)
user0721090601

2
jjmerelo: Den Vorschlag finden Sie unter gist.github.com/alabamenhu/2fec7a8f51a24091dc1b104a2ae2f04d . Ich bin ein paar Tage davon entfernt, ein Testmodul zu zeigen, aber ich habe den größten Teil der Logistik des Binex in Betrieb, aber für die Raku-ähnliche Syntax
user0721090601

Antworten:


5

-1. Einschränkungen (nur für Pakete)

Die Methode EXPORTHOW ruft .set_how auf, wenn aktuell $?LANGein Slang hinzugefügt wird.
Dann ist es add_package_declarator auf die , MAIN $?LANGdie ein fügt package_declaratorVerfahren zu seinen Aktionen und Grammatik. Ich denke, es ist der einzige "dynamische Slang" (in World.nqp).

Wenn Sie route_declarator überschreiben möchten . Dann müssen Sie einen Slang schreiben, der die gerade zitierte Kette imitiert. Wenn Sie akzeptieren, das Schlüsselwort method beizubehalten und die automatische Signatur in der Klasse zu erstellen, z. B. entsprechend dem Methodennamen, haben Sie folgende Möglichkeiten:

Hinweis: Ein Paket ist ein Container (Paket, Grammatik, Modul, Rolle, Know-how, Aufzählung, Klasse, Teilmenge). Wenn Sie Code wie eine Methode einfügen, wird dieser ausgeführt (ich habe es gerade versucht):

0. Beschreibung (EXPORTHOW)

Ich würde EXPORTHOW ohne Papiere und DECLAREin einem Modul verwenden, weil ich mit Phaser keinen Weg gefunden habe . Anscheinend ist es auch bei BEGIN zu spät.

Das Beispiel, das ich gebe, ist das Dekorieren jeder Methode in einer Klasse (gerade 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. Ausführbar

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

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

4. Quellen


Ausgezeichnet. Einfach und unkompliziert. Vielen Dank!
user0721090601
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.