2016-08-15 9 views
9

次のように私は新しいタイプTupleを定義しました:なぜPerl6は追加後に配列の長さをチェックしませんか?

subset Tuple of Array where { .elems == 2 && .[0] < .[1] }; 
my Tuple $t = [1, 2]; 
say $t; # [1 2] So far, so good. 

予想通り、私は、短いまたは長い配列または[2, 1]でそれを初期化できません。しかし、私はそれに追加することができます:

$t.append(3); 
say $t; # [1 2 3] Ouch! 

どのように可能ですか?

答えて

4

型制約はスカラーコンテナにバインドされていますが、含まれるオブジェクトは単なる古い配列です。配列のappendメソッドは、型チェックをトリガーすることを知らせていません。

チェックを再度明示的にトリガーする場合は、$t = $tのような再割り当てを行うことができます。

6

my Tuple $tは、$t変数を作成して、その変数への(再)割り当てまたは(再)バインドがTuple型チェックに合格する必要があります。

= [1, 2]は、Arrayオブジェクトへの参照を割り当てます。 Tupleタイプのチェックが適用されます(およびパスします)。

$t.append(3)$tで開催されたArrayオブジェクトの内容を変更しますが、$tを再割り当てまたは再バインドされませんので、何の型チェックはありません。

$t.append(3)ではなく$t.=append(3)の代わりのメソッド呼び出し構文は、$tの型チェックをトリガします。

境界チェックされた配列(my @array[2]など)には特定の構文がありますが、私はそれがあなたの質問のポイントではないと推測しています。

1

実際に変更されたバージョンのArrayが必要な場合は、それを継承するクラスを作成して、異なる振る舞いをするメソッドをオーバーライドするだけで済みます。 (そこにこれを行うには、おそらくはるかにエレガントな方法がありますが、これは作業を行う):あなたが期待するよう

class Tuple is Array { 
    method append (*@val) { 
     fail '"append" is disabled for Tuples' 
    } 
} 

my $t = Tuple.new(1,2); 

say $t; 

$t.append(3); 

そして、それは動作します:

[1 2] 
"append" is disabled for Tuples 
    in method append at example.p6 line 2 
    in block <unit> at example.p6 line 11 

Actually thrown at: 
    in block <unit> at example.p6 line 11 

代わりに、あなたが使用することができ似た何かを得るために次元配列as mentioned by raiph。または、配列に似た不変なものが必要な場合は、Listを使用できます。

関連する問題