Thread Block vs. Hashref (25 answers)
Opened by barney at 2024-08-02 13:17

haj
 2024-08-07 14:00
#196644 #196644
User since
2015-01-07
558 Artikel
BenutzerIn

user image
Vor der "Lösung" aus dem Blog-Artikel möchte ich warnen:
Code (perl): (dl )
my %hash = "here" => $_ for grep { -d $_ } qw{a b c .};

Der Autor feiert das als "kein Syntaxfehler" und "schneller", aber das ist absoluter Blödsinn, aus mehreren Gründen. Nach der Ausführung hat man das Äquivalent von:
Code (perl): (dl )
my %hash = ("here" => undef);

Erstens ist es Unsinn, einen Hash aufzubauen, bei dem der Schlüssel immer den gleichen Wert hat, wie Rosti auch schon geschrieben hat. Aber zweitens ist die Präzedenz der Operatoren nicht so, wie der Autor vielleicht meint.
Man muss da schon Klammern setzen:
Code (perl): (dl )
my %hash = ("here" => $_) for grep { -d $_ } qw{a b c .};

In %hash = "here" => $_  ist das Komma der Komma-Operator: Der linke Teil %hash = "here" wird ausgeführt, dann der Wert drangehängt, das nach der for-Schleife in $_ drin ist. Weil '.' als das aktuelle Verzeichnis ziemlich sicher den -d-Test besteht, ist das '.'. Das Ergebnis des Statements, das im Blog-Artikel verworfen wird, ist also die Liste ('here',undef,'.').

Code: (dl )
1
2
3
4
$ perl -MData::Dumper -E 'print Dumper %hash = "here" => $_ for grep { -d $_ } qw{a b c .}'
$VAR1 = 'here';
$VAR2 = undef;
$VAR3 = '.';

Mit dem Modul Perldoc:B::Deparse kann man sich die tatsächliche Klammerhierarchie auch zeigen lassen:
Code: (dl )
1
2
3
4
$ perl -MO=Deparse,-p -E '%hash = "here" => $_ for grep { -d $_ } qw{. a b c eg}'
use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
((%hash = 'here'), $_) foreach (grep({(-d $_);} '.', 'a', 'b', 'c', 'eg'));
-e syntax OK

View full thread Block vs. Hashref