2011-01-12 6 views

Antwort

12
sub f { 
    return [@_]; 
} 

$ref = f(2, 3, 5); 
print "@$ref\n"; 

[@foo] Das Konstrukt erzeugt einen Verweis auf eine neue, anonymes Array (Kopie des @foo), während die \@foo Konstrukt eine Referenz auf das Array @foo erzeugt, dessen Inhalt möglicherweise später ändern.

2

Es gibt ein paar Möglichkeiten, um ein Unterprogramm zu erstellen, das seine Argumente als Array zurückgibt:

sub array {[@_]} # returns an array reference that is a copy of its argument 

sub array_verbose { # the same as array(), but spelled out 
    my @copy = @_; 
    return \@copy; 
} 

sub capture {\@_} # returns a reference to the actual argument array 

Es gibt einige wichtige Unterschiede zwischen array und capture:

my ($x, $y) = (3, 4); 

my $array = array $x, $y; 
my $capture = capture $x, $y; 

say "@$array, @$capture"; # prints '3 4, 3 4' 

$x++; 

say "@$array, @$capture"; # prints '3 4, 4 4' 

$$capture[1] *= 2; 

say "@$array, @$capture"; # prints '3 4, 4 8' 

say "$x $y"; # prints '4 8' 

Wie diese Beispiele zeigen, Das von array() erzeugte Array wird nach Wert kopiert, und diese Werte sind unabhängig von den ursprünglichen Argumenten. Das Array, das von capture() erzeugt wird, behält einen bidirektionalen Alias ​​zu seiner Argumentliste bei.

Ein weiterer Unterschied ist die Geschwindigkeit. capture() ist ungefähr 40% schneller als array(), da es die Elemente des Arrays nicht kopieren muss (oder sie sogar anschauen muss). Dieser Geschwindigkeitsunterschied variiert natürlich abhängig von der Länge der Argumentliste.

Ein zusätzlicher Effekt von capture() nicht einmal, dass seine Elemente zu berühren, wenn ein Argument, das normalerweise Speicher verwendet wird zuteilen würde, wird nicht, dass die Zuteilung passieren, bis das Argument berührt wird:

my %hash; 
my $hashcap = capture $hash{a}, $hash{b}, $hash{c}; 

say join ', ' => keys %hash; # prints nothing 

$_++ for @$hashcap; 

say join ', ' => keys %hash; # prints 'c, a, b' 

In meinem eigenen Code, Ich buchstabiere normalerweise capture() als cap() oder schreibe es einfach inline:

my $y = sub{\@_}->(map $_**2, 1..10); 
Verwandte Themen