2017-10-13 20 views
2

私は属性特性を作成しようとしています。このユースケースは、オブジェクトからドキュメントへのマッピングの文脈で、クラスのいくつかの属性を "crudable"としてマークすることです。Perl 6 - メタ属性を設定する属性特性を作成できますか?

role crud { 
    has Bool $.crud is default(True); 
} 

multi trait_mod:<is>(Attribute $a, crud, $arg) { 
    $a.container.VAR does crud($arg); 
} 

class Foo { 
    has $.bar is rw; 

    # Provide an extra nested information 
    has $.baz is rw is crud(True); 
} 

some example codeを読んで、適応させることによって、私は私がやりたいように見える何かを得ることができました。ここはa snippet with test caseです。

私は新しいFooオブジェクトをインスタンス化し、$.bar属性(isないcrudという)を設定すると、それは次のようになります。

.Foo @0 
├ $.bar is rw = 123456789 
└ $.baz is rw = .Scalar+{crud} @1 
    └ $.crud +{crud} = True 

私はこのことから理解して何が$.baz属性が、私が呼んでいるものだということですメタ属性は、潜在的な値から独立しています。

(私がここでやったことを正しく理解すれば、私の形質は汚れたハックではありません)。 True$foo.baz.crudに到達することが可能です。しかし、私は非常によく理解していない.Scalar+{crud}の意味、そしてもし私が何かを設定することができれば。私は属性$.bazインスタンスを設定しようとすると

、このエラーが返されます。

Cannot modify an immutable Scalar+{crud} (Scalar+{crud}.new(crud => Bool::True)) 
    in block <unit> at t/08-attribute-trait.t line 30 

注:これは私が得ることができた作業溶液に最も近いものです。私はインスタンス化されたFooクラスの異なるインスタンスのための異なるcrud設定を必要としません。

ブール値を変更することは決してありません。実際にオブジェクトがインスタンス化された後は、という属性にis crudという属性を指定するだけです。 TrueまたはFalseの値を引数として渡すことにも関心がありません。ブール値の属性属性をデフォルトでTrueに設定するだけで十分です。私はこのようにすることはできませんでした。

multi trait_mod:<is>(Attribute $a, :$crud!) { 
    # Something like this 
    $a.container.VAR does set-crud; 
} 

class Foo { 
    has $.bar is rw; 
    has $.baz is rw is crud; 
} 

私は何かできないことをしようとしていますか?このユースケースを達成するためにこのコードをどのように適応させることができますか?

+2

'crud'は引数を取らないので、' crud($ arg) 'は何をしているのか説明できますか?または、それが偽のコードのように見えて、とにかくこの質問のあなたの焦点に関係がないと言っていることを考えれば、それを編集してください。言い換えれば、コードの最後のビットを質問の中核にして、コードの最初のビットを捨ててください。それは理にかなっていますか? – raiph

+2

ああ!質問の簡略化されたバージョン( '$ arg'を無視して)を与えられたとき、あなたは単に' 'crud {}の役割をしようとしているようです。クラスFoo {は、$ .bazがrwがcrudです}; say Foo.new.baz ~~クルード; #True'は現在実行していることではなく、 "まだ実装されていない$ -sigil変数の特性です。"と不平を言います。私は何マイル離れていますか?...? – raiph

+2

もし私が何マイルも離れていなければ、 '' crud {}の回避策はどうでしょうか?クラスFoo {は@ .bazがrwはcrudです}; say Foo.new.baz ~~クルード; #True'、つまりスカラーの代わりに配列を使用していますか? – raiph

答えて

4

ここではいくつかのことが起こっています。まず第一に、trait_modの署名が間違っているように見えます。第二に、形質の名前が既存の役割と同じである場合、悪い相互作用があるように見えます。私はこれがNYIの例外であるべきだと考えていますが、明らかに構文解析で間違っているか、エラーメッセージを生成しようとして間違っています。

とにかく、私は、これはあなたが欲しいものだと思う:

role CRUD {}; # since CRUD is used as an acronym, I chose to use uppercase here 

multi trait_mod:<is>(Attribute:D $a, :$crud!) { # note required named attribute! 
    $a.^mixin: CRUD if $crud; # mixin the CRUD role if a True value was given 
} 

class A { 
    has $.a is crud(False); # too bad "is !crud" is invalid syntax 
    has $.b is crud; 
} 

say "$_.name(): { $_ ~~ CRUD }" for A.^attributes; # $!a: False, $!b: True 

は、この情報がお役に立てば幸いです。

+0

ありがとうエリザベス、それは多くの助けて! Naoum Hankacheの "Perl 6 Introduction"(クイックスタートには非常に明確で効果的です)を読んだだけで、先週Perl6で作業を始めたので、自分でこれを行う方法を見つけるのは難しかったです。私は "Perl6 at a glance"の本のコピーを待っていて、もっと発見することに非常に興奮しています。 – smonff

関連する問題