How to pass an array of functions to Perl?

Question 1:

I want to pass an array to a function. But the argument passed changes in the function. Is this called by value?

Question 2:

#my ($name, $num, @array)= @_; <=1 ) my $name = shift; <=2 ) my $num = shift; my @array = shift; 

Case 1 and 2 have a different output. Why did this happen?

 #!/usr/bin/perl use strict; my @test1; push @test1, ['a', 1]; push @test1, ['b', 1]; push @test1, ['c', 1]; push @test1, ['d', 1]; push @test1, ['e', 1]; for (my $i=0; $i< scalar(@test1); $i++) { print "out1: $test1[$i][0] $test1[$i][1]\n"; } test_func("test_func", 10, @test1); sub test_func { #my ($name, $num, @array)= @_; <=1) my $name = shift; <=2) my $num = shift; my @array = shift; print "$name\n"; print "$num\n"; for (my $i=0; $i< scalar(@test1); $i++) { print "$array[$i][0] $array[$i][1]\n"; } for (my $i=0; $i< scalar(@test1); $i++) { if ($array[$i][0] eq 'a') { $array[$i][0] = 'z'; } } for (my $i=0; $i< scalar(@test1); $i++) { print "change: $array[$i][0] $array[$i][1]\n"; } } for (my $i=0; $i< scalar(@test1); $i++) { print "out2: $test1[$i][0] $test1[$i][1]\n"; } 
#

Below is the test output.

 out1: a 1 out1: b 1 out1: c 1 out1: d 1 out1: e 1 test_func 10 a 1 b 1 c 1 d 1 e 1 change: z 1 change: b 1 change: c 1 change: d 1 change: e 1 out2: z 1 <= Why did it change? out2: b 1 out2: c 1 out2: d 1 out2: e 1 
+6
source share
1 answer
I want to pass an array of function [...] with another output. Why did this happen?

You cannot pass an array to a function . Subs can only accept a list of scalars as arguments.

 test_func("test_func", 10, @test1); 

coincides with

 test_func("test_func", 10, $test1[0], $test1[1], $test1[2], $test1[3], $test1[4]); 

You create a new array in test_func when you execute

 my ($name, $num, @array) = @_; 

shift returns the first @_ element, which is necessarily a scalar. @_ is an array, and array elements are scalars. Equivalent to be

 my $name = shift(@_); my $num = shift(@_); my @array = splice(@_); 

To pass an array to sub, you can usually pass a reference to it.

 test_func("test_func", 10, \@test1); my ($name, $num, $array) = @_; my $name = shift; my $num = shift; my $array = shift; say "@$array"; 

But the argument passed changes in the function. Is this called by value?

Perl never goes by value. It always follows the link. If you change any @_ element, it will change the corresponding argument in the caller.

 $ perl -E'sub f { $_[0] = "def"; } my $x = "abc"; f($x); say $x;' def 

But it's not a problem. You do not change any @_ elements. What you are doing is changing the only array referenced by both $test[0] and $array[0] .

This is what you do:

 my $ref1 = [ 'a', 1 ]; # aka $test1[0] my $ref2 = $ref1; # aka $array[0] $ref2->[0] = 'z'; # Changes the single array (not $ref1 or $ref2). 

This is short for

 my @anon = ( 'a', 1 ); my $ref1 = \@anon; # aka $test1[0] my $ref2 = $ref1; # aka $array[0] $ref2->[0] = 'z'; # Changes @anon (not $ref1 or $ref2). 

Storable dclone can be used to create a deep copy of an array.

 my $ref1 = [ 'a', 1 ]; my $ref2 = dclone($ref1); # clones the reference, the array, 'a' and 1. $ref1->[0] = 'y'; # Changes the original array $ref2->[0] = 'z'; # Changes the new array 
+10
source

Source: https://habr.com/ru/post/916370/


All Articles