2016-01-27 24 views
8

Questa è una sottigliezza che ho trovato con keys().Perché l'autovivificazione si verifica con le chiavi() e non con% {..}?

$ perl -e 'use warnings; use strict; my $d = { "ab" => 1 }; my @e = keys(%{$d->{cd}});' 

$ perl -e 'use warnings; use strict; my $d = { "ab" => 1 }; my %e = %{$d->{cd}};' 
Can't use an undefined value as a HASH reference at -e line 1. 

Sono molto perplesso sul motivo per cui il primo frammento di non darebbe un errore dereferencing. Quando uso Data::Dumper, diventa chiaro che nel primo frammento, $d->{cd}, viene autovivificato per essere {}.

Perché è necessario automatizzare lo keys? Ho provato a leggere il perldoc per questo, non ho trovato una risposta soddisfacente. keys non imposta un alias ($_, ecc.) Quindi perl non è necessario pensare che $d->{cd} debba essere nel contesto di lvalue, c'è? (Ho capito se l'espressione deve essere in lvalue contesto autovivificazione accade come spiegato here.

Un rilevante post.

+5

https://rt.perl.org/Public/Bug/Display.html?id=118983 – ThisSuitIsBlackNot

risposta

3

Nota che le chiavi possono infatti essere un lvalue (impostazione numero previsto del hash di elementi).

Ma anche se le chiavi per sé non è utilizzato in un contesto lvalue, ha un effetto collaterale di resettare iteratore di un hash.

in modo che non modifica l'hash e così dà al dereference un contesto lvalue, il che lo rende autovivify

0

Dopo alcune ricerche e domande in giro, ho scoperto che questo ha a che fare con il fatto che $d->{cd} è stato passato a una subroutine, non al fatto che era keys. Ad esempio,

% perl -e 'use warnings; use strict; my $d = { "ab" => 1 }; sub foo {}; my @e = foo(%{$d->{cd}});' 

Questo sarà anche autovivify; questo perché internamente perl deve essere in grado di impostare un alias per gli argomenti della funzione.

All'interno foo(), abbiamo un alias set $_[0] = $d->{cd} Ma questo significa $d->{cd} deve essere lvalue-in grado, dal momento che le subroutine in perl presuppongono che si può fare qualcosa di simile in modo che il $_[0] = "123"; autovivificazione deve accadere.

+0

Hai ragione sugli argomenti di subroutine che sono lvalue, ma 'keys' è un operatore, non una subroutine. L'argomento di 'keys' è trattato come un lvalue, ma questo non è il caso per tutti gli operatori. Confronta 'perl -E'keys% $ h; dì $ h'' a 'perl -E'length% $ h; dì $ h''. – ThisSuitIsBlackNot

Problemi correlati