Почему «существует» изменяет мою константу? - PullRequest
7 голосов
/ 20 октября 2010

Функция exists может неожиданно автоматически оживлять записи в хешах.

Что меня удивляет, так это то, что это поведение распространяется и на константы:

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

Выход

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

Я подозреваю, что это ошибка. Это что-то специфичное для 5.10.1, или другие версии Perl ведут себя аналогично?

Ответы [ 2 ]

15 голосов
/ 20 октября 2010

Это документированное поведение. константа perldoc говорит:

Даже если ссылка может быть объявлен как константа, ссылка может указывать на данные, которые могут быть изменилось, как показывает этот код.

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

Это постоянная ссылка, а не то, к чему она относится.

9 голосов
/ 20 октября 2010

Возможно, вы захотите использовать Readonly для создания "истинных" констант.

Константы, созданные с использованием прагмы constant, на самом деле встроенные подпрограммы .Это означает, что во время компиляции соответствующая скалярная константа вставляется непосредственно вместо некоторого вызова подпрограммы.Если константа является ссылкой, ничто не мешает вам изменить данные, на которые она указывает.

...