Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where are perl constants replaced by their values?

Tags:

constants

perl

I tried to use constant values in perl and stumbled upon the following weird behaviour:

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

use constant {
    a => "b"
};

my $c = { a => a };
my %d;
$d{a} = a;

print Dumper($c);
print Dumper(\%d);

will output

$VAR1 = {
          'a' => 'b'
        };
$VAR1 = {
          'a' => 'b'
        };

The constant a was replaced on the right hand side of the expressions $d{a} = a and a => a, but not on the left side.

I know that constants are implemented using inlinable subs (documented here) and that sub names evaluate to their names if they aren't predeclared (documented here), but I can see no reason why in my example a evaluates once to the value and once to the name in the same line of code, especially in the assignment to the hash - The a => a might be a consequence of => interpreting the left site as a string if it begins with a letter.

Sidenote: Adding parantheses to make the sub-call explicit yields the expected result:

# ...
my $c = { a() => a }; # or my $c = { a, a };
my %d;
$d{a()} = a;
# ....

Output:

$VAR1 = {
          'b' => 'b'
        };
$VAR1 = {
          'b' => 'b'
        };

(all examples tested with perl 5.18)

like image 325
urzeit Avatar asked Dec 12 '16 05:12

urzeit


1 Answers

The end of the constant page, at CAVEATS, has the answer

You can get into trouble if you use constants in a context which automatically quotes barewords (as is true for any subroutine call). For example, you can't say $hash{CONSTANT} because CONSTANT will be interpreted as a string.

It then proceeds with the solution you found

Use $hash{CONSTANT()} or $hash{+CONSTANT} to prevent the bareword quoting mechanism from kicking in.

Then it spells this out for hashes as well

Similarly, since the => operator quotes a bareword immediately to its left, you have to say CONSTANT() => 'value' (or simply use a comma in place of the big arrow) instead of CONSTANT => 'value'.

like image 108
zdim Avatar answered Sep 30 '22 00:09

zdim