W Perl wszystkie argumenty funkcji są przekazywane przez tablicę @_. Podczas wywołania subprogramu wszystkie przekazane parametry znajdują się w tej tablicy i początkowo jest to lista, a nie kopia, co oznacza, że jeśli zmienisz $_[0], modyfikujesz oryginał.
sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # Tylko lokalna zmienna się zmienia }
sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @data teraz (1,2,3,42)
my ($a, $b) = @_ tworzone są kopie.Jeśli w Perl funkcji przekażesz tablicę tak:
myfunc(@arr), a w środku funkcji odniesiesz się do$_[0], co tam będzie?
Poprawna odpowiedź: Będzie tam pierwszy element wartości tablicy, a nie referencja do całej tablicy! Aby przekazać tablicę jako cały obiekt, użyj referencji: myfunc(\@arr).
sub print_first { print $_[0], " "; } my @a = qw/foo bar baz/; print_first(@a); # Wyświetli 'foo', a nie referencję do tablicy print_first(\@a); # Wyświetli ARRAY(0x...) — referencję do całej tablicy
Historia
update_hash(%global). Wewnątrz zmieniano $_[0]. W rezultacie — zmieniano tylko lokalny wycinek tablicy argumentów, a sam globalny hash nie był modyfikowany. Poprawnym rozwiązaniem stało się przekazywanie referencji: update_hash(\%global).Historia
myfunc(@arr, %opts). Okazało się, że część kluczy hashy była zastępowana wartościami tablicy, a zauważenie błędu było trudne.Historia
Podczas implementacji rekurencyjnego przeszukiwania drzewa chciano zmieniać wewnętrzne elementy. Do funkcji przekazywano tablice "jak są", nie przez referencję. Tworzono kopie, a zmiany w żaden sposób nie wpływały na kontekst zewnętrzny. Problem rozwiązano poprzez zastąpienie przekazań stylem referencyjnym.