A much saner way to undefine slices is @a[@i] = () ° ¹
DB<26> @a = (2 .. 9);
DB<27> @i = (2, 3, 5);
DB<28> @a[@i] = ()
DB<29> @b = grep defined, @a;
DB<30> x @a
0 2
1 3
2 undef
3 undef
4 6
5 undef
6 8
7 9
DB<31> x @b
0 2
1 3
2 6
3 8
4 9
DB<32>
...
DB<65> p exists $a[0]
1
DB<66> p defined $a[0]
DB<67>
Like with hashes is delete not assigning undef but kicking the element's value out of existence.
Now the size of hashes is shrinking by the number of deleted elements. But with arrays this only happens for elements at the end of the array, which is shortened then. While this is consistent with the use of exists , it might lead to unpredictable behavior.*
This explains the stark warning.
DB<40> @a = (0..4)
DB<41> delete @a[0,2,4]
DB<42> p exists $a[0]
DB<43> p exists $a[1]
1
DB<44> x @a # shortened
0 undef
1 1
2 undef
3 3
DB<45> p scalar @a
4
DB<46>
Bottom line: only use delete with arrays if you really want to differentiate between defined and exists and this shrinking behavior is anticipated.
In order to remove array elements use splice. If you need sparse arrays, consider using hashes with numbers as keys. *
footnotes
°) unfortunately is undef @arr[@slice] not DWIM.
*) Paragraph rephrased
¹) and @b = grep exists, @a; is the way to go together with delete. This way you won't get caught by accidental undef values.
update
To better highlight that undef is an existing value but non existence is translated to undef after assignment:
DB<56> x @a
0 undef
1 1
2 undef
3 3
DB<57> $a[5] = undef
DB<58> x @a
0 undef
1 1
2 undef
3 3
4 undef. # gap
5 undef. # value
DB<59> p exists $a[4]
DB<60> p exists $a[5]
1
DB<61>
|