Thread Perl und @*
(35 answers)
Opened by barney at 2023-11-09 09:47
Ich versuche es nochmal. Das erkannte "Problem" besteht aus zwei Komponenten, die hier zwangsläufig kombiniert sind:
Das Problem ist nun die Syntax am Ende: ->@*. So ist es ein Postfix-Deref, der alle Elemente der enthaltenen Referenz holen soll. Wenn man das > vergisst, wird da eine Subtraktion -@* draus. Oder wenn man das - weglässt, ein Vergleich >@*. In beiden Fällen wird @* "plötzlich" als Array gewertet, ohne dass eine Warnung oder ein Fehler erscheint. Eben weil diese Interpunktionsvariablen eine Sonderbehandlung erfahren (siehe oben oder in perlvar). In beiden Fällen steht @* nun im skalaren Kontext und liefert die Anzahl seiner Elemente zurück; in der Regel dürfte das 0 sein. Im ersten Fall wird also 0 von der Speicheradresse der Referenz abgezogen; im zweiten Fall wird ein Vergleich durchgeführt, ob die Speicheradresse der Referenz größer 0 ist; normalerweise "ja", dargestellt durch die "1". Je nach Situation ist dieser Fehler kaum zu erkennen. Und das ist nicht auf die Array-Syntax beschränkt! Ähnliches kann bei ->%* und auch passieren; wobei es da wahrscheinlich eher auffällt, weil: Bei aktivierten Warnungen kommt eine Meldung, wenn man eine ungerade Anzahl von Elementen an einnen Hash zuweist. Code (perl): (dl
)
1 2 3 4 5 6 use warnings; ## WICHTIG!!!! my $hash_ref = { key => 'value' }; my %ergebnis = $hash_ref-%*; ## odd number of elements my %ergebnis = $hash_ref>%*; ## odd number of elements Ohne warnings kriegt man das aber auch nicht mit! Bei $* hat man mehr Schutz, weil diese Variable früher mal vordefiniert war und jetzt diese Funktion nicht mehr hat. Da sollte der Perl-Compiler selbst ohne strict und warnings schon beim Start aussteigen. Veranschauungsskript für Array und Hash: Code (perl): (dl
)
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 #! /usr/bin/env perl use strict; use warnings; use 5.024; use Data::Dumper; $Data::Dumper::Useqq = 1; my $aRef = [ qw( 123 ) ]; say "\$aRef ist Array-Referenz mit Anzahl Elementen: ", 0+@$aRef; say Data::Dumper->new([ $aRef ], [ 'aRef'] )->Useqq(1)->Dump; # my @ergebnisse; @ergebnisse = @$aRef; say join " ", "Ergebnis (klassisch mit \@\$aRef):", @ergebnisse; @ergebnisse = $aRef->@*; say join " ", "Ergebnis (postfix deref mit ->\@\*):", @ergebnisse; @ergebnisse = $aRef-@*; say join " ", "Ergebnis (Tippfehler mit -\@\*):", @ergebnisse; @ergebnisse = $aRef>@*; say join " ", "Ergebnis (Tippfehler mit >\@\*):", @ergebnisse; ################ # say "\n", "###"x20, "\n"; my $hRef = { foo => "bar" }; say "\$hRef ist Hash-Referenz mit Anzahl Paaren: ", 0+(keys %$hRef); say Data::Dumper->new([ $hRef ], [ 'hRef'] )->Useqq(1)->Dump; my %ergebnisse; %ergebnisse = $hRef->%*; say join " ", "Ergebnis (postfix deref mit ->\%\*):", %ergebnisse; say Data::Dumper->new([ \%ergebnisse ], [ '*ergebnisse'] )->Useqq(1)->Dump; my %ergebnisse = $hRef-@*; say join " ", "Ergebnis (Tippfehler mit -\%\*):", %ergebnisse; say Data::Dumper->new([ \%ergebnisse ], [ '*ergebnisse'] )->Useqq(1)->Dump; @ergebnisse = $hRef>%*; say join " ", "Ergebnis (Tippfehler mit >\%\*):", %ergebnisse; say Data::Dumper->new([ \%ergebnisse ], [ '*ergebnisse'] )->Useqq(1)->Dump; say "\n\n## ABER: die letzten zwei nochmal OHNE warnings...\n"; { no warnings; my %ergebnisse = $hRef-@*; say join " ", "Ergebnis (Tippfehler mit -\%\*):", %ergebnisse; say Data::Dumper->new([ \%ergebnisse ], [ '*ergebnisse'] )->Useqq(1)->Dump; @ergebnisse = $hRef>%*; say join " ", "Ergebnis (Tippfehler mit >\%\*):", %ergebnisse; say Data::Dumper->new([ \%ergebnisse ], [ '*ergebnisse'] )->Useqq(1)->Dump; } __END__ meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen! |