2016-01-06 12 views
7

Dlaczego następujący kod:niespójne zachowanie dotyczące „Nie można użyć nieokreślonej wartości jako odniesienie tablicy”

use strict; 
use warnings; 
no warnings 'uninitialized'; 

use Data::Dumper; 

my $user; 
my @data = @{$user->{ENTERPRISE}}; # Error on this line 
print Dumper($user), qq{Done!\n}; 

rzucać błąd „Can't use an undefined value as an ARRAY reference”, podczas następującego kodu:

use strict; 
use warnings; 
no warnings 'uninitialized'; 

use Data::Dumper; 

my $user; 
foreach my $enterprise(@{$user->{ENTERPRISES}}) { 
    print qq{Enterprise:}, $enterprise; 
} 
print Dumper($user), qq{Done!\n}; 

Nic nie wrzuca, ale zamiast tego zwraca:

$VAR1 = { 
      'ENTERPRISES' => [] 
     }; 
Done! 

Oba mają naruszającego dorsza w nich, ale tylko jeden rzuca błąd.

możliwa odpowiedź:Perl's autovivification?

Jestem na dobrej drodze tutaj? Dzięki za wkład.

+1

Co właściwie próbujesz zrobić? To, że wyłączyłeś ostrzeżenia, powinno być naprawdę dobrym sygnałem ostrzegawczym, że nie jest to dobry pomysł. – Sobrique

+0

Próbuję tylko dowiedzieć się, co Perl robi, aby rzucić błąd w jednym miejscu, a nie w innym na ten sam kawałek kodu. Pierwszy blok kodu pochodzi ze starszego kodu, który zgłasza błąd i musi zostać naprawiony, podczas gdy drugi blok kodu jest nowszym kodem, o który się martwię, będzie również potrzebował poprawki, ale chyba nie, ponieważ nie rzuca błędu, który widziałem w przeszłości. – Morrowind789

Odpowiedz

9

Tak, to, co wydarzyło się w drugim przypadku, nazywa się autoworyzacją, a stało się to tylko w drugim przypadku, ponieważ autoworyzacja występuje tylko dla wartości l: [1].

Więc

@{ $x } = $y; 

oznacza

@{ $x //= [] } = $y; 

ale

$y = @{ $x }; 

nie oznacza

$y = @{ $x //= [] }; 

Należy pamiętać, że foreach przypisuje zmienną pętli do każdego elementu listy, nad którą jest iterowany, więc te elementy są oceniane jako l-wartości.

Autoworyzacja jest dokumentowana w perlref, a można kontrolować autoworyzację za pomocą pragma autovivification.


  1. Jeśli końcowy deferencing następuje przez indeksowania (np ->[] lub ->{}), wyrażenie odniesienia sam jest oceniana jako lwartości, nawet jeśli nie jest indeksowana całość. Oznacza to, że $y = $x->[0]; i $y = ${ $x }[0]; można automatycznie włączyć $x, nawet jeśli $y = @{ $x }; nie będzie.
+0

To jest bardzo pouczające. Twoja ostatnia uwaga na temat tego, jak działa foreach, polegająca na aliasowaniu zmiennej pętli powodującej, że jesteśmy w sytuacji lwartej, naprawdę rozjaśnia sprawę. Czy rozróżnienie między lwartością a rwartością zostało gdzieś oficjalnie udokumentowane? – Morrowind789

+0

@ Morrowind789 Jest krótko wspomniany w ['perldoc perlref'] (http://perldoc.perl.org/perlref.html # Using-References) w punkcie # 3 w "Korzystanie z referencji". Także w definicji autoworyzacji w [perlglossary] (http://perldoc.perl.org/perlglossary.html#autovivification). – ThisSuitIsBlackNot

+0

Dokumentacja dla autowikularyzacji (w [perlref] (http://perldoc.perl.org/perlref.html)): "Jest to jeden z przypadków, o których wspominaliśmy wcześniej, w których odniesienia mogą powstać, gdy są w kontekście lwartości . [...] Proces ten nazywa się autoworyzacją. " – ikegami

Powiązane problemy