Leser: 27
1 2 3 4 5 6 7 8 9 10 11 12
#!/usr/bin/perl -w use strict; use warnings; use Data::Dumper; my @ab = ("Emma", "Paul"); test(\@ab); sub test { my $ref = $_[0]; print Dumper($ref); }
2011-02-26T07:07:42 biancaZum Beispiel zur Übergabe an eine Sub könnte man das verwenden. Dann wird nur eine Referenz zum Array übergeben und nicht das ganze Array. Eine Referenz braucht nach meinem Kenntnisstand weniger internen Arbeitsspeicher.
1
2
3
4
5
perl -w -MData::Dumper -e 'sub abc{print Dumper \@_ }; abc(1,2)';
$VAR1 = [
1,
2
];
1
2
3
4
5
6
7
8
9
10
11
12
perl -w -MData::Dumper -e '@a=[1,2,{1=>{2=>"i"}}]; sub abc{print Dumper \@_ }; abc(@a)';
$VAR1 = [
[
1,
2,
{
'1' => {
'2' => 'i'
}
}
]
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bernhard@Fitz:~$ perl -w -MData::Dumper -e 'my @a=[1,2,{1=>{2=>"i"}}]; sub abc{print Dumper( \@a, \@_ ) }; abc(@a)';
$VAR1 = [
[
1,
2,
{
'1' => {
'2' => 'i'
}
}
]
];
$VAR2 = [
$VAR1->[0]
];
2011-02-26T10:26:17 BernhardSchmalhoferNein, bei der Übergabe einer Referenz an eine Subrouting wird keine tiefe Kopie erstellt.
2011-02-26T08:05:55 leo11Subs in Perl sind immer call-by-reference.Bei der Erstellung von @_ macht es einen Unterschied in Performance und Speicherverbrauch ob nur eine Referenz kopiert werden muss, oder die komletten Daten. Des Weiteren kommt hinzu, dass man in der sub die Originaldaten manipulieren kann, sofern man eine Referenz übergibt. Möchte man sichergehen, das das nicht passiert, sollte man lieber auf einer Kopie der Daten arbeiten.
1 2 3 4 5 6 7 8 9
sub bla { s/a/u/g for @_; } my @ar=qw/faa bar baz/; bla(@ar); print "@ar"; __END__ fuu bur buz
perl -w -MData::Dumper -e '@a=[1,2,{1=>{2=>"i"}}]; sub abc{print Dumper \@_ }; abc(@a)';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
use strict;
use warnings;
use Data::Dumper;
# the first arg will modified
sub square_first_arg {
$_[0] = $_[0]** 2;
}
my $x = 2;
square_first_arg($x);
print "2 squared is $x\n";
eval {
square_first_arg( 3 );
};
print "trying to square something unmodifyable: $@ \n";
# Referenzen
my $a = 'A';
sub a_to_b {
# copy @_, as we dont't want to modify the the param itself
my ($first_param) = @_;
# modify the scalar that $first_param refers to
${ $first_param } = 'B';
}
print Dumper( $a );
a_to_b( \$a );
print Dumper( $a );
1
2
3
4
5
6
7
8
9
10
11
perl -wE'
sub foo {
$_[0]++
}
my @a = 1 .. 3;
say "@a";
foo(@a);
say "@a";
'
1 2 3
2 2 3
2011-02-26T21:09:33 hugenyn
Ein anonymes Array kann man verwenden, wenn in einer Sub via @_ das
Original verändert werden soll/darf.
2011-02-26T21:09:33 hugenynAnsonsten übergibt man der Sub ein benanntes Array. In diesem Fall verändert die Manipulation in @_ das Original nicht.
2011-02-26T21:09:33 hugenynDas anonyme Array wäre folglich nur für die Arbeit mit Subs von Vorteil.
2011-02-26T21:09:33 hugenynIch fasse mal zusammen, wie ich die Antworten verstanden habe:
Ein anonymes Array kann man verwenden, wenn in einer Sub via @_ das Original verändert werden soll/darf.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#! /usr/bin/perl -l use strict; use warnings; sub exchange_values { # tausche inhalte des ersten und zweiten elements mit Hilfe des @_ (Alias) @_[0,1] = @_[1,0]; } my $hello = 'World!'; my $world = 'Hello '; # kontrolle; so ist's jetzt print $hello, $world; exchange_values( $hello, $world ); # ups; das war eben noch anders print $hello, $world;
QuoteAnsonsten übergibt man der Sub ein benanntes Array. In diesem Fall verändert die Manipulation in @_ das Original nicht.
1 2 3 4
sub foo ( # originale sind sicher; wir kopieren die Inhalte my ( $anton, $berta ) = @_; }
QuoteEin verändertes @_ gibt man bei Bedarf per Return an ein anderes Array zurück.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
sub exchange_words { # kopiere die Werte in eigene Variablen my ( $word1, $word2 ) = @_; # Woerter tauschen ( $word1, $word2 ) = ( $word2, $word1 ); # gebe die veraenderten Werte zurueck return ( $word1, $word2 ); } my ($hello, $world) = exchange_words( 'world!', 'hello ' ); print $hello, $world;
QuoteDas anonyme Array wäre folglich nur für die Arbeit mit Subs von Vorteil.
QuoteHoffentlich richtig verstanden.
QuoteWenn Du Werte in @_ veränderst, veränderst Du die originalen Werte
1
2
3
4
5
6
7
8
9
10
my @wp = qw /Vater Mutter Kind/;
say "Start-Array: @wp";
&oma(@wp);
sub oma {
say "\@_ in sub: @_";
@_ =();
say "\@_in sub gelöscht: @_";
}
say "Original nach sub: @wp";
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#! /usr/bin/perl -l use strict; use warnings; sub amok { print "\@_ before amok: @_"; # kill'em all by implicit alias for my $k ( 0 .. $#_ ) { $_[$k] = 'kill'; } print "\@_ after amok: @_"; } my @wp = qw( Vater Mutter Kind ); print "start: @wp"; amok(@wp); print "ende: @wp";
Quote(Hervorhebungen von mir)... Any arguments passed in show up in the array @_. Therefore, if you called a function with two arguments, those would be stored in $_[0] and $_[1].
The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding
argument is updated (or an error occurs if it is not updatable). If an argument is an array or hash element which did not exist when the function was called,
that element is created only when (and if) it is modified or a reference to it is taken. (Some earlier versions of Perl created the element whether or not
the element was assigned to.) Assigning to the whole array @_ removes that aliasing, and does not update any arguments. ...