2010-10-20 8 views
7

Funkcja exists może mieć wartości unexpectedly autovivify entries w hasłach.Dlaczego `istnieje` modyfikuje moją stałą?

Co mnie dziwi to, że to zachowanie przenosi się na stałe, a także:

use strict; 
use warnings; 
use Data::Dump 'dump'; 

use constant data => { 
         'foo' => { 
            'bar' => 'baz', 
           }, 
         'a' => { 
            'b' => 'c', 
           } 
        }; 

dump data; # Pre-modified 

print "No data for 'soda->cola->pop'\n" unless exists data->{soda}{cola}{pop}; 

dump data; # data->{soda}{cola} now sprung to life 

Wyjście

{ a => { b => "c" }, foo => { bar => "baz" } } 
No data for 'soda->cola->pop' 
{ a => { b => "c" }, foo => { bar => "baz" }, soda => { cola => {} } } 

I podejrzewam, że jest to błąd. Czy jest to coś specyficznego dla wersji 5.10.1, czy też inne wersje Perla zachowują się podobnie?

+4

Możesz wyłączyć autoworyzację dla dowolnego zakresu leksykalnego za pomocą "nie [autoworyzacja] (http://search.cpan.org/perldoc?autovivification)". – rafl

+0

Moje pytanie dotyczyło bardziej zmiennego zachowania stałych z "istnieniem" niż tego, jak można tego uniknąć. – Zaid

+3

podczas pracy ze stałymi pamiętaj, że 'użyj stałej PI => 3.14' jest tym samym, co' sub PI() {3.14} ', a' use constant data => {...} 'is' {my $ data = { ...}; sub dane() {$ dane}} ' –

Odpowiedz

15

To jest udokumentowane zachowanie. perldoc constant mówi:

Mimo odniesienia może być zadeklarowana jako stała, odniesienie może wskazywać na danych, które mogą być zmieniło, jak ilustruje to poniższy kod.

use constant ARRAY => [ 1,2,3,4 ]; 
print ARRAY->[1]; 
ARRAY->[1] = " be changed"; 
print ARRAY->[1]; 

To odniesienie że jest stała, nie to, co się odnosi.

+0

Czy możesz wyjaśnić, dlaczego Perl zgłasza błąd "Nie można modyfikować stałego elementu w przypisaniu skalarnym" dla 'use constant var => 50; var = 40; ' – Zaid

+2

Ponieważ próbujesz zmienić stałą. I nie możesz tego zrobić. Stałe są ... cóż ... stałe. O to właśnie chodzi. Wartość skalarna przechowywana w stałej nie może zostać zmieniona. Ale kiedy tworzysz stałą z odnośnika hash (jak w twoim przykładzie), to jest odniesienie, które jest poprawione, a nie dane, do których masz odniesienie. Odniesieniem jest wartość skalarna, która jest przechowywana w stałej. –

+0

Dobre rzeczy, chciałbym móc +2 tę odpowiedź. – Zaid

9

Prawdopodobnie chcesz użyć Readonly do tworzenia "prawdziwych" stałych.

Stałe utworzone przy użyciu pragma constant są w rzeczywistości inlinable subroutines. Oznacza to, że w czasie kompilacji odpowiednia stała skalarna jest wstawiana bezpośrednio w miejsce wywołania podprogramu. Jeśli stała jest referencją, nic nie stoi na przeszkodzie, aby zmienić dane, na które wskazuje.

+0

Czy stała wartość stała jest stałą skalarną? – Zaid

+1

Nie widzę, jak to jest odpowiedź na pytanie? – ysth

+0

Użyj czegoś takiego jak Data :: Lock (część Attribute :: Constant) zamiast Readonly. – MkV