Ich versuche es nochmal. Das erkannte "Problem" besteht aus zwei Komponenten, die hier zwangsläufig kombiniert sind:
- 1.) Variablen mit Interpunktionszeichen, die nicht deklariert werden müssen, sondern eine Sonderbehandlung erfahren, siehe
perlvar
Das gilt für alle Typen; Skalare, Arrays, und Hashes
Hier konkret: @* und auch %*
Ausser den vordefinierten Variablen dieser Klasse (wie $., $?, $/, ...) sollte man die nicht in normalen Skripten nutzen. Klare Variablennamen sind toll und zu bevorzugen.
1
2
3
4
5
6
7
8
9
10
11
12
use strict;
use warnings;
use 5.024;
say for @*;
say for %*;
say for @named_array;
say for %hash_with_name;
(Zum Testen die letzten beiden Zeilen erstmal weglassen oder kommentieren; dann einfügen oder aktivieren und nochmal testen.)
- 2.) die Syntax der Postfix-Derefenzierung: siehe
perlref Postfix-Dereference-Syntax
Wenn man mit der neu eingeführten Syntax alle Elemente eines referenzierten Arrays aus einer einfachen oder komplexen Datenstruktur holen will, kann man das jetzt auch mit einem nachgelagerten ->@* tun.
Ist soweit ja ganz ok.
@elements = @$array_ref;
@elements = @{ $array_ref };
@elements = $array_ref->@*;
Gerade bei komplexen Strukturen mag das angenehmer sein, dass man keine geschweiften Klammern drumrum setzen muss.
Man kann die Struktur von links nach rechts lesen und am Ende steht da, was man daraus holen will:
@elements = @{$hashref->[0]->{keyname}->[23]->{kinder}};
@elements = $hashref->[0]->{keyname}->[23]->{kinder}->@*;
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.
use warnings;
my $hash_ref = { key => 'value' };
my %ergebnis = $hash_ref-%*;
my %ergebnis = $hash_ref>%*;
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:
testskript.pl (16.6kb)
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!