W Perl wynik przypisania (a tym samym operacji na tablicach i hashach) zależy od kontekstu.
my @arr = (10, 20, 30); my $count = @arr; # $count == 3 my ($first, $second) = @arr; # $first == 10, $second == 20
Dla hashy:
my %h = (a=>1, b=>2, c=>3); my $size = %h; # $size == 3 w nowoczesnych wersjach Perla, ale wcześniej tak nie było!
Uważaj na przypisanie całej referencji do tablicy zamiast skopiowania zawartości!
Czym różni się przypisanie tablicy do referencji i skopiowanie zawartości tablicy?
Odpowiedź:
my @a = (1,2,3); my $ref = \@a; # $ref — referencja do tablicy, zmiany przez $ref są widoczne w @a my @b = @a; # @b — nowa tablica, zmiany @b nie wpływają na @a # Porównaj: push @$ref, 4; # @a teraz (1,2,3,4) push @b, 5; # @a pozostaje (1,2,3,4); @b — (1,2,3,5)
Historia 1
W projekcie przekazywano tablicę do podprogramu przez referencję, nie rozumiejąc, że to rzeczywiście jest referencja: funkcja zmieniała ją w miejscu wywołania. Pojawiły się błędy — w kodzie wywołującym struktura danych została już "zepsuta". Oczekiwano kopii, dostali alias.
Historia 2
Inżynier zakładał, że przypisanie skalarne
%hzwróci rzeczywistą liczbę par. Okazało się — w starszych wersjach Perla to zachowanie było inne: zwracano liczbę miejsc/koszyków, a nie długość! W rezultacie czasami zwracano nie 3, a inną liczbę, co zepsuło statystyki.
Historia 3
W dużym systemie ETL tablice kopiowano przez referencje, a potem niespodziewanie nadpisywano sobie dane, ponieważ wszyscy pracowali z tą samą tablicą, a nie z niezależnymi kopiami. Diagnostyka błędu zajęła kilka dni.