perl – Why is `exists` modifying my constant? – Education Career Blog

The exists function can unexpectedly autovivify entries in hashes.

What surprises me is that this behavior carries over to constants as well:

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

Output

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

I suspect this is a bug. Is this something 5.10.1-specific, or do other versions of Perl behave similarly?

,

This is documented behaviour. perldoc constant says:

Even though a reference may be
declared as a constant, the reference
may point to data which may be
changed, as this code shows.

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

It’s the reference that is constant, not what it refers to.

,

You probably want to use Readonly for creating “true” constants.

Constants created using the constant pragma are actually inlinable subroutines. It means that at compile time the appropriate scalar constant is inserted directly in place of some subroutine call. If the constant is a reference, nothing prevents you from changing the data it points to.

Leave a Comment