2016-12-02 7 views
3

Perl5のほとんどの場合と同様に、その属性のカスタム型変換をサポートするクラスを作成する方法はたくさんあります。ここでは、単純な1は、配列リファレンスからハッシュに、です:Perl6クラスの属性の型変換

#!/usr/bin/env perl 

package Local::Class { 
    use Moo; 
    use Types::Standard qw(HashRef ArrayRef); 

    has set => (
    is => 'ro', 
    coerce => 1, 
    isa => HashRef->plus_coercions(
     ArrayRef, sub { return { map { $_ => 1} @{$_[0]} } }, 
    ), 
); 
} 

my $o = Local::Class->new({ set => [qw(a b b c)] }); 
# $o->set now holds { a => 1, b => 1, c => 1} 

私はそれが私がSetHashArrayを強制する方法です必要なもののように思えるPerl6の、このようなポート何かにしようとしてきました。これまでのところ、私はそれを行うことができました唯一の方法は、このようなものです:

#!/usr/bin/env perl6 

class Local::Class { 
    has %.set; 
    ## Wanted to have 
    # has %.set is SetHash; 
    ## but it dies with "Cannot modify an immutable SetHash" 

    submethod TWEAK (:$set) { 
    self.set = $set.SetHash; 
    } 
} 

my $o = Local::Class.new(set => [< a b b c >]); 
# $o.set now holds {:a, :b, :c} 

しかし、これは非常に少なくとも、小さなディテールのために、それを行うには正しい方法であると私には思えません。奇数番号のリストをコンストラクタに渡すと、スクリプトは死んでしまいます。

これはPerl6でどのように行われますか?クラス属性のカスタム型強制を実装するための推奨される方法は何ですか(複数あると確信しています)。

答えて

3

TWEAKオブジェクトがBUILDで初期化された後で実行されます。これは、奇数番目の配列を指定すると爆発します。

BUILD時間に強制を移動

、そして期待通りのものが動作するはずです:

class Local::Class { 
    has %.set; 
    submethod BUILD (:$set) { 
    %!set := $set.SetHash; 
    } 
} 

あなたは属性の自動初期化と組み合わせて強制変換SetHash()パラメータの型を使用することができればそれはいいだろうが、これはと失敗します。 sigilは属性の名前の一部です。非結合型を受け入れる場合は、パラメータを%-sigilledにすることはできません。

あなたの代わりに$ -sigilled属性を使用している場合しかし、それは正常に動作します:

class Local::Class { 
    has $.set; 
    submethod BUILD (SetHash() :$!set) {} 
} 

@smlsが指摘するように、以下のバリアント

class Local::Class { 
    has %.set is SetHash; 
    submethod BUILD (:$set) { 
    %!set = $set.SetHash; 
    } 
} 

は、おそらく同様に動作するはずです不変のSetHashを変更することはできません。

SetHashがアサインされていないため、回避策は、あなたが私は実際に動作するようになっていると思い

class Local::Class { 
    has %.set is SetHash; 
    submethod BUILD (:$set) { 
    %!set{$set.SetHash.keys} = True xx *; 
    } 
} 
+2

を使用することができますように '%の.SETがSetHashであり;並びに、'、および「不変SetHashを変更することはできません"というのは、ちょうど楽しいバグです。 – smls

+1

@smls:agree; cf edit – Christoph

+1

'サブメソッドBUILD(SetHash():$ set){%!set:= $ set}'も同様に動作します –

関連する問題