Thread Rückgabe mehrerer Hashes geht nicht
(22 answers)
Opened by SchaubFD at 2008-02-13 09:24 SchaubFD+2008-02-13 13:40:07-- Deine Frage ist berechtigt, und da muss man weiter ausholen. es betrifft nicht nur Parameterübergaben sondern hängt mit der Besonderheit von Perl bezüglich verschachtelten Strukturen zusammen, die nur mit Referenzen möglich sind. Generell gilt, dass man Listen von Skalaren Elementweise aufeinander abbilden kann. Code (perl): (dl
)
( $a, $b, $c ) = ( 1, 2, 3 ) ;# => $a=1, $b=2 usw. trägt man aber rechtsseitig ein Array oder Hash ein, wird es alles zu einer eindimensionalen Liste abgeflacht (Flattening), also: Code (perl): (dl
)
1 2 3 4 5 6 7 @x = ( x1, x2, x3 ); %y=( y1 => "Y1 ); ( $a, $b, $c ) = ( %y, $x, 1, 2, 3 ); # = ( y1, Y1, x1, x2, x3, 1, 2, 3) # => $a == "y1", $b == "Y1", $c == "x1" Linksseitig wirkt der erste eingetragenen Array oder Hash wie ein Staubsauger, der alle folgenden Skalare aufnimmt Code (perl): (dl
)
1 2 3 ($a,$b,@X,$c) = (%y,$x,1,2,3); # => @X = (x1,x2,x3,1,2,3) , $a = "y1", $b = "Y1", # => insbesondere $c = undef wenn du also schreibst: Code (perl): (dl
)
( @X ) = ( @x ) dann klappt deine Zuweisung, die Inhalte von @x werden 1zu1 auf @X umkopiert Hingegen Code (perl): (dl
)
( @X , @Y ) = ( @x , @y ) liefert aber nur @X == ( @x , @y ) und @Y == () Referenzen hingegen werden wie Skalare behandelt, d.h. kein Aufsaugen! Code (perl): (dl
)
( $X_ref , $Y_ref ) = ( \@x , \@y ) Es funktioniert und hat den entscheidenden Unterschied dass hier keine einzelnen Arrayelemente umkopiert werden, sondern dass es sich auf beiden Seiten um die gleiche Referenz des selben Arrays handelt. also Das ist ein entscheidender Vorteil, wenn man die übergebenen Arrays/Hashs direkt manipulieren will, aber auch das eventuell große Datenmengen nicht unnötig herumumkopiert werden müssen. Was dich (wie auch mich) wohl nervt ist das du fortan immer den Pfeil mitschreiben musst um zu dereferenzieren. Je nachdem ob du auf ein Alias oder eine Kopie zugreifen willst kannst du auch wieder derefrenzieren Code (perl): (dl
)
1 2 @X = @$X_ref ; kopiert die Werte nach @X um *X = $X_ref ; legt ein Alias an, also \@X==\$X_ref das letzte Konstrukt ist ein Typglob und ist mit Vorsicht zu genießen, weil es nur mit Packagevariablen funktioniert, dafür aber recht stringent, du kannst nämlich schreiben Code (perl): (dl
)
( *X , *Y , $A )=( \@x , \@y , $a) Weil du damit aber keine lexikalischen (my) Variablen aliasen kannst wird dir das aber heutzutage kaum jmd empfehlen.... dafür gibts in Perl5 leider keinen eingebauten Mechanismus, einziger Ausweg wäre da, das Modul ![]() Als die moderneren my-Variablen eingeführt wurden, wurde leider versäumt deren Aliasing direkt mit einzubauen. Bedenke bitte das es in anderen Sprachen auch nur Referenzen übergeben werden, allerdings implizit! In Javascript z.B. eine Referenz auf ein Array-Objekt. Umkopieren oder Flattening musst du da auch (mit Ausnahmen) explizit fordern. In Perl ist es halt defaultmäßig eingebaut, und muss daher im Bedarfsfall explizit verhindert werden. Das hat Vor- und Nachteile, Perl erlaubt z.B. Konstrukte wie Code (perl): (dl
)
( $a , $b , $c , @X ) = ( @X ) oder Code (perl): (dl
)
%A = ( %A, %B, %C ) Dabei werden mehrfach vorkommende Keys überschrieben werden. (%B dominiert %A, %C dominiert alle anderen, usw) SchaubFD+2008-02-13 13:40:07-- Ein einzelnes Hash kannst du wie oben gezeigt per Einzelwerte umkopieren. Bei mehreren kommst du an Referenzen nicht vorbei, ein zusätzlicher Backslash wird dich auch kaum umbringen. AFAIK gilt übrigens auch Code (perl): (dl
)
\( %a , %b ) == ( \%a , \%b ) womit du noch mehr Backslashes einsparen könntest, wenn nur Referenzen übergeben werden. TMTOWTDYOG (there's more than one way to dig your own grave)
|