choroba
choroba

Reputation: 242103

Why doesn't Perl6 check the array length after append?

I've defined a new type Tuple as follows:

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

I can't initialize it with shorter or longer array or with [2, 1], as expected. But, I can append to it:

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

How's that possible?

Upvotes: 9

Views: 156

Answers (3)

Christopher Bottoms
Christopher Bottoms

Reputation: 11168

If you really want an altered version of an Array, you can simply create a class that inherits from it and overrides the methods that you want to behave differently. (There are probably much more elegant ways to do this, but this does work):

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

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

say $t;

$t.append(3);

Then it will work like you expect:

[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

Alternately, to get something similar you could use a dimensioned array as mentioned by raiph. Or, if you simply want something immutable that is similar to an array, you can then use a List.

Upvotes: 1

raiph
raiph

Reputation: 32489

my Tuple $t creates a $t variable such that any (re)assignment or (re)binding to it must (re)pass the Tuple type check.

= [1, 2] assigns a reference to an Array object. The Tuple type check is applied (and passes).

$t.append(3) modifies the contents of the Array object held in $t but does not reassign or rebind $t so there's no type check.

Mutating-method-call syntax -- $t.=append(3) instead of $t.append(3) -- will trigger the type check on $t.

There is specific syntax for a bounds-checked array (my @array[2] etc.) but I'm guessing that's not the point of your question.

Upvotes: 6

Christoph
Christoph

Reputation: 169713

The type constraint is bound to the scalar container, but the object it contains is just a plain old array - and an array's append method is unaware you want it to trigger a type check.

If you want to explicitly trigger the check again, you could do a reassignment like $t = $t.

Upvotes: 4

Related Questions