Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is `exists` modifying my constant?

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?

like image 541
Zaid Avatar asked Oct 20 '10 09:10

Zaid


2 Answers

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.

like image 61
Dave Cross Avatar answered Oct 16 '22 13:10

Dave Cross


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.

like image 28
Eugene Yarmash Avatar answered Oct 16 '22 13:10

Eugene Yarmash