in reply to Re: why doesn't constant work?
in thread why doesn't constant work?

Is there anyway I can force it into being eval'ed for the value of constant? (or do I have to put it a variable...?)

Replies are listed 'Best First'.
Re^3: why doesn't constant work?
by Tanktalus (Canon) on Nov 11, 2010 at 04:41 UTC
    #/usr/bin/perl use strict; use warnings; use constant { Undefined => 0, Page => 1, Index => 2, }; {my %map = ( Page => 'mypage', Index => 'myindex', ); use Data::Dumper qw(Dumper); print Dumper \%map;} {my %map = ( Page() => 'mypage', Index() => 'myindex', ); print Dumper \%map;}

    And this is why Perl Best Practices says to use Readonly (with Readonly::XS installed, preferably) instead of constant.

    Well, one of the reasons anyway. Another is string interpolation. And I think there are more, though I can't remember them off the top of my head :-)

      Readonly is a lovely module, but a small caveat about Readonly - if you don't have control over the Perl interpreter that will be running your script, you may suffer a significant performance penalty using Readonly, espcially if your script or application needs to use the constants to process large batches of information (e.g. Bioinformatics)

      According to the documentation, Readonly is about 20x slower than Constant unless it dedetcts the module Readonly::XS is installed. If the XS module is installed, then scalar readonly constants will be about the same speed as non-scalar constants (the XS modules simply flips the scalar's read-only bit in the underlying C-code). However, this works only for scalar constants. For all other constants (arrays, hashes) you still have the speed penalty.

      If your script will run on a statically installed version of Perl, you will have to recompile the Perl binary to include the XS module (it isn't part of the standard compile). To include XS module in dynamically linked Perl interpreters, you at least need permission to compile and install C libraries - not always a straight forward matter in corporate environments or when you are developing for a client environment rather than one you have personal control over.

        To include XS module in dynamically linked Perl interpreters, you at least need permission to compile and install C libraries - not always a straight forward matter in corporate environments or when you are developing for a client environment rather than one you have personal control over.
        The phrase "if X is installed, Y will be 20 times faster" is often a good start.

        But a variable being readonly isn't a requirement for correctness. It's a development tool. So you can do something like:

        BEGIN { if (IS_PRODUCTION) { eval <<'SUB'; sub Readonly (\[$@%]@) { given (ref $_[0]) { when ('SCALAR') {${$_[0]} = $_[1]} when ('ARRAY') {@{$_[0]} = @_[1 .. $#_]} when ('HASH') {%{$_[0]} = @_[1 .. $#_]} } } SUB } else { require Readonly; Readonly->import; } }
        You'll have your Readonly variables in development, and no dependency in production.
Re^3: why doesn't constant work?
by roboticus (Chancellor) on Nov 11, 2010 at 04:27 UTC

    perl-diddler:

    From the docs:

    The "=>" operator is a synonym for the comma except that it causes its left operand to be interpreted as a string if it begins with a letter or underscore and is composed only of letters, digits and underscores. This includes operands that might otherwise be interpreted as operators, constants, single number v-strings or function calls. If in doubt about this behaviour, the left operand can be quoted explicitly.

    So I'd suggest just using a comma:

    my %map = ( Page, 'mypage', Index, 'myindex', );

    Notes: (1) Untested, as I don't recall ever using the constant module before, and (2) Yes, it looks strange to me, too!

    ...roboticus