2016-08-15 9 views
9

Mam zdefiniowany nowy typ Tuple następująco:Dlaczego Perl6 nie sprawdza długości tablicy po dodaniu?

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

Nie mogę zainicjować go z krótszym lub dłuższym tablicy lub z [2, 1], jak oczekiwano. Ale mogę dodać:

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

Jak to możliwe?

Odpowiedz

4

Ograniczenie typu jest przypisane do kontenera skalarnego, ale obiekt, który zawiera, jest po prostu zwykłą starą tablicą - a metoda tablicowa append nie jest świadoma, że ​​ma wywołać kontrolę typu.

Jeśli chcesz ponownie aktywować czek ponownie, możesz zmienić przypisanie, na przykład $t = $t.

6

my Tuple $t tworzy zmienną taką, że każde (ponowne) przyporządkowanie lub (ponowne) powiązanie z nią musi (ponownie) przejść test typu typu: Tuple.

= [1, 2] przydziela odniesienie do obiektu Array. Sprawdzanie typu Tuple jest stosowane (i przechodzi).

$t.append(3) modyfikuje zawartość obiektu Array odbyło się w $t ale nie przypisanie lub ponownie powiązać $t więc nie sprawdzić typ.

Składnia metody Mutating - wywołanie metody - $t.=append(3) zamiast $t.append(3) - uruchomi sprawdzanie typu na $t.

Istnieje specyficzna składnia dla tablicy sprawdzanej przez granice (my @array[2] itd.), Ale domyślam się, że nie o to pytasz.

1

Jeśli naprawdę chcesz zmienić wersję Array, możesz po prostu utworzyć klasę, która dziedziczy po niej i nadpisuje metody, które chcesz inaczej zachowywać. (Istnieją prawdopodobnie znacznie bardziej elegancki sposób, aby to zrobić, ale to działa):

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

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

say $t; 

$t.append(3); 

Wtedy to będzie działać jak można się spodziewać:

[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 

Naprzemiennie dostać coś podobnego można użyć zwymiarowana tablica as mentioned by raiph. Lub, jeśli po prostu chcesz czegoś niezmiennego, który jest podobny do tablicy, możesz użyć List.