カスタム宣言子を作る


9

特定のボイラープレートのセットをかなり定期的に使用するとします。

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

}

私はむしろただ言うことができるほうがいいです:

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

そして、Barのどこかで、barの宣言を設定します(または、クラスFoo自体が最終的に独自の宣言子を使用するため、別の場所に移動でき、別のTypeで引き出す必要はありません)。どうすればいいですか?


これは基本的には「どうすればいいですか?」しかし、実際の記事は見たことがありません。それを使用している現存のモジュール(Red / Cro)は、一見して理解するのが難しいかなり複雑な(美しい場合)獣です。
user0721090601

署名を再利用したいですね。
jjmerelo

2
jjmerelo:いいえ、実際の最終的な目標は、メソッドサブクラス(クラス内で使用する場合はクラスに登録する)を行い、コードブロック内で完全に異なる言語(この場合は正規表現のような言語)を使用することです
user0721090601

2
jjmerelo:提案についてはgist.github.com/alabamenhu/2fec7a8f51a24091dc1b104a2ae2f04dを参照してください。表示するテストモジュールを作成するのに数日かかりますが、Binexのほとんどのロジスティクスは機能していますが、Rakuに似た構文
user0721090601

回答:


5

-1。制限(パッケージのみ)

メソッドEXPORTHOWは、現在のスラングを後者に追加するとき.set_howを呼び出します$?LANG
次に、アクションと文法にメソッドを追加するにadd_package_declaratorMAIN $?LANG追加しますpackage_declarator。私は、これが唯一の「動的スラング」(World.nqp内)だと思います。

あなたが望むのは、routine_declaratorを上書きすることです。次に、引用したチェーンを模倣したスラングを記述する必要があります。methodキーワードを保持し、メソッド名に従ってクラスで自動署名を行うことに同意した場合、次の方法があります。

注: パッケージはコンテナです(パッケージ、文法、モジュール、ロール、ノウハウ、列挙型、クラス、サブセット)。メソッドのように内部にコードを置くと、これが実行されます(私は試してみました):

0.説明(EXPORTHOW)

私はPhaserで方法を見つけられなかったので、文書化されていないEXPORTHOWモジュールを使用しDECLAREました。どうやらBEGINでも手遅れです。

私が与える例は、クラスのすべてのメソッドを装飾しています(も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.実行可能

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.出力

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

4.ソース


優秀な。シンプルでわかりやすい。ありがとう!
user0721090601
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.