2016-08-15 2 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) изменяет содержимое Array объекта, состоявшегося в $t, но не переназначение или перепривязывает $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.

Смежные вопросы