Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

What is the difference between the constant construct in Perl and the Readonly construct in Perl?

by jira0004 (Monk)
on Jul 06, 2006 at 00:48 UTC ( #559456=perlquestion: print w/ replies, xml ) Need Help??
jira0004 has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

Perl provides two different constructs to allow a developer to set up a symbol for a value that will be used through out a package, but will not change; these two different constructs are constant and Readonly. Once a constant or a Readonly symbol is defined in a Perl package, it can not be changed else where in the package although it can be used as many times as the developer wishes.

Thus, in Perl there are two standard ways I could define a constant of PI (to six decimal places of accuracy) in my Perl program:

use constant PI => 3.141593;

OR

use Readonly PI => 3.141593;

After using either constant or Readonly to define PI in my program, I can use it as a symbol in my program over and over again, although as the terms imply, I can not change its value.

Here is what I want to know:

  • What are the differences between constant and Readonly in Perl?
  • Why would I want to use one over the other? Or are they pretty much the same and hence there is no reason to choose one over the other?
  • In what version of Perl did constant come into being?
  • In what version of Perl did Readonly come into being?
  • Which of the two do you use if either and why?

Thanks!

Comment on What is the difference between the constant construct in Perl and the Readonly construct in Perl?
Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by revdiablo (Prior) on Jul 06, 2006 at 00:58 UTC

    I think some of your basic assumptions might be incorrect. It does not appear that Readonly is a core module, and it appears that you have the syntax for its usage wrong. From what I'm seeing, Readonly allows you to set a normal, sigil-bearing variable to read only, and use it in the standard manner. By comparison, constant gives you a bareword constant that you can't use in all the same contexts as a normal variable (e.g. stringwise evaluation of scalars). So it my mind, it boils down to the following tradeoff:

    Is the cost of installing the CPAN module outweighed by the utility of being able to use the value more conveniently?

    And that's really something you need to answer for yourself.

    Update: for future reference, you can see what modules are included in the standard perl distribution by reading perlmodlib. And you can also find what version a certain module became core with the help of Module::CoreList.

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by jdtoronto (Prior) on Jul 06, 2006 at 01:19 UTC
    As revdiablo has said Readonly is not a core module, whereas constant is a pragma. There are some shortcomings in the use of the constant pragma and all of those are in fact well pointed out in the documentation for Readonly. However Readonly has a performance penalty and there is at least one 'speed up' module ( Readonly::xs ) on CPAN for it and some useful alternatives. One particularly cunning one is Scalar::Readonly which although it works only on scalars allows you to programatically 'write enable' a variable, update it and then lock it again. Of course the variable can be tested as well.

    I will very rarely use constant, I have never used Readonly. We do some tricks using Scalar::Readonly ocasionally.

    jdtoronto

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by xdg (Monsignor) on Jul 06, 2006 at 01:20 UTC

    Also, according to Re^3: Import constants as scalar instead of bareword sub, Readonly uses tie (even in XS mode), which will have a speed hit.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by diotalevi (Canon) on Jul 06, 2006 at 01:26 UTC

    The author of Readonly has inspired my ire by neglecting to mention the positive reasons to use constant. I wrote a note at AnnoCPAN and I'm reproducing it for you here as well.

    You didn't mention that the constant pragma allows the value to get inlined into the optree. You also didn't mention that when constants are used in conditionals, perl is able to optimize away the non-executable branches.

    Further you didn't mention that constant.pm tracks perl's preferred implementation for constants. Prior to 5.9.4 constants were implemented as functions like sub FOO () { 1 }. After that perl does something a little bit different which allows for a smaller memory footprint.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      I agree. that was one of the few things I didn't like while reading PBP.
      To many people speed doesn't seem to be important. But if I hadn't used constant in my HTC module, it would probably be much slower than it is (I use a lot of constants there...)
      and I think at least in modules speed is a bit more important than in application code.
        From PBP page 58:
        If you decide not [to] use the Readonly module in production code (for performance or political reasons), then using constant is still better than using literal values.

        From that quote I get the impression that TheDamian is aware of the performance issues but takes for granted that others are not as familiar. Regardless however, the performance issue is mentioned in PBP (albeit briefly).

        Update: Fixed typos

      well, i think speed is always an issue!

        While you're often right with this, and certainly in this case too (++), be careful not to generalise:

        In many other places, speed may not be so much of an issue =)

        Cheers, Sören

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by davido (Archbishop) on Jul 06, 2006 at 01:27 UTC

    The Readonly module doesn't work as you demonstrate. The code you provided:

    use Readonly PI => 3.141593;

    will generate the following error message:

    Readonly version 3.14 required--this is only version 1.03 at C:/Perl/l +ib/Exporter/Heavy.pm line 121. BEGIN failed--compilation aborted at mytest.pl line 5.

    You probably mean to say the following:

    use Readonly; Readonly my $PI => 3.141592654; print "$PI\n";

    In which case, it should be immediately apparent what the differences between use constant and Readonly are. For one thing, the Readonly function creates a readonly scalar, hash, or array. These entities can be lexically scoped or they can be package globals. And they retain most of the characteristics of an ordinary Perl variable. They have a sigil ($, %, or @), and interpolation rules follow those of any ordinary Perl variable. These enhancements over the tired use constant pragma are significant, and solve issues that diminished the usefulness of the constant pragma.

    If you were to try to modify that readonly variable, as in $PI = 3.5;, Readonly will die with an error message like this: Modification of a read-only value attempted at test.pl line 13.

    There are a few other pros to using Readonly, and a Con also (having to do with speed), which can be improved upon by also installing Readonly::XS. Have a look at the documentation for Readonly, and I think you'll see. It provides a great list of pros and cons, and also describes the implications of installing the XS companion module. I was turned on to the module by reading Perl Best Practices.


    Dave

      Im assuming that Readonly does the same thing as Internals::SvREADONLY($scalar, 1); which is XS and is available as of 5.8

      ---
      $world=~s/war/peace/g

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by BrowserUk (Pope) on Jul 06, 2006 at 02:07 UTC

    Besides all the optimisation features of constant so carefully omitted by the Readonly docs (as noted by diotalevi++), another of things I especially like about

    use constant SYMBOL => 123;,

    is that my constants don't look like variables.

    All the hyperbole about Readonly exported variables being immutable makes me think of nothing more than the old saying about constants that aren't and variables that won't. I cannot imagine why anyone would want their constants to look like variables?

    The minor inconvenience of using (s)printf in order to embed the values of constants into strings is actually a plus. If I define pi in my program, I'm gonna define it to the full accuracy of whatever math I'm using supports. For standard floats that's use constant PI => 3.1415926535897931; in order to use the best accuracy in my calculations. But if I'm going to display pi, I'm probably going to settle for showing 3 or 4 decimal places. (s)printf are the tool for this, so it works out great.

    Another ill-thought through solution to a non-problem foisted on the world under the title of a best practice.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I cannot imagine why anyone would want their constants to look like variables?
      Because variables Do What We Want without constant bletcherosity like the $foo{+BAR} hack? Which is buried way down in the bugs section of perldoc constant where nobody is going to see it, by the way. Seriously, someone ought to collect up all the "How do I do X with a constant?" FAQs and answer them right up at the top of the documentation.
      Another ill-thought through solution to a non-problem foisted on the world under the title of a best practice.

      My God, your hyperbole knob must be twisted all the way to 11 and broken way off. Has it ever occurred to you that perhaps different people have different priorities than you, and every expression thereof should not be taken as an affront to your very way of life? Because I'll tell you what, if that though ever has occurred to you, you seem to have dismissed it with the same vengeance you use to attack any idea that doesn't suit your world view.

        I've attempted to contribute to the debate in the form of logical argument in favour of one side and against the other.

        I finished with one line of untargetted, polite, opinion. No affront. No vengance. No attack. Heathly debate, backed by reasoning and ended with a little personal opinion.

        And your post contributes what? Certainly nothing to the debate. Just a cowardly, anonymous ad hominim attack because my opinion differs from yours. Get a backbone and if your opinion is based on anything other than kneejerk, reactionary contrariness, try stating your reasoning, and adding to the debate instead of attacking me.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      For standard floats that's use constant PI => 3.1415926535897931;

      I can't help but comment, even if it's OT, obscure, and makes absolutely no practical difference. It's still, ever so slightly, wrong It should be

      PI => 3.1415926535897932;

      There, I feel better.

      By the way, I thought your closing, "Another ill-thought through solution to a non-problem foisted on the world under the title of a best practice." was a nice expression of opinion, both precise and articulate (though not at all one with which I agree.) However, if one doesn't read it carefully, it can remind those in the US of a typical american rant, and there's now doubt those who took it that way. (Over here, we're little familliar with the articulate verbal sparring of Gladsone and Disraeli, or their decendants.) I'm just offering clarification; I'm not suggesting you do anything differently.

        PI => 3.1415926535897932;

        Ah but...

        printf "%19.17f\n", 3.1415926535897932;; 3.14159265358979310

        Blame IEEE 754, not me :)

        ... articulate verbal sparring of Gladsone and Disraeli ...

        I wish. Baldrick maybe ;)


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by duff (Vicar) on Jul 06, 2006 at 02:53 UTC

    If some more of perl6 makes it into perl5 we might have a third option before long--a constant declarator. Here's what it will look like in perl6:

    constant $PI = 3.141593;
    See the section of Synopsis 3 on declarators for more info.

    This should be easy to hack into perl5 for scalars, but I'm not sure about arrays and such.

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by tfrayner (Curate) on Jul 06, 2006 at 09:36 UTC
    Hi,

    A key feature (in my view) of Readonly that others haven't mentioned yet is that a Readonly hashref will prevent you from modifying the referenced hash. The constant pragma, in contrast, only prevents you from changing the top-level reference value. The constant will always point to the same hash, but that hash can be modified. Maybe this might change in future, I don't know, but in the meantime I've been bitten by this not-entirely-constant nature of the constant pragma (inadvertently using a "constant" hash as a global variable...). It's fine for scalar and array values, but a bit dodgy for hashes, IMHO.

    cheers,
    Tim

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by Moron (Curate) on Jul 06, 2006 at 13:59 UTC
    A constant causes lexical substitution to take place for instances of the bareword found within the scope of the constant declaration.

    Readonly controls access to variables not barewords.

    The conditions for Readonly instead of using a constant bareword tend to be where the "constant" value is unknown prior to entry into the relevant scope, whereas a constant is known in advance of execution and tends to be used to minimise hardcoding.

    # example of constant: # use constant TMPDIR = '/bigdrive/bigbucket01'; use constant TMPDIR = '/tmp'; # /tmp now mapped to above # example of Readonly: sub Write { my $self = shift; Readonly my %reset = %$self; # ... code that modifies $self # e.g. with 'dangerous' use of eval ... $self -> ( STATE } = eval $self -> { COMMAND } or goto ERROR; # ... $self -> Close() and return 1; # if error reset $self: ERROR: delete $self -> { $_} for keys %$self; $self -> { $_ } = $reset{ $_ } for keys %reset; return 0; }

    -M

    Free your mind

Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by PerlingTheUK (Hermit) on Jul 07, 2006 at 11:36 UTC
    Other than just the above mentioned it also allows you to assign an array or hash directly as Readonly.
    Readonly my @vals => (1,2,3,4); Readonly my %vals => (1=>2);
    If I am not mistaken constant is also assigned at compile time. So using Readonly inside a function to take the parameters would work, the same would not work for constant.

    Cheers,
    PerlingTheUK
Re: What is the difference between the constant construct in Perl and the Readonly construct in Perl?
by demerphq (Chancellor) on Jul 07, 2006 at 13:23 UTC

    Personally I think that I wouldnt use the Readonly module. Partially because what it does is done elsewhere, and i'd be more likely to look there, (Hash::Util for instance would be where i would look for locked hashes). But also because the semantics of readonlyness IMO isnt all that clear. For instance should the readonlyness transfer on assignment? (It doesn't).

    The other thing that makes me wonder, is why does the module go to such extreme lengths? Making a constant scalar (which seems to me to be a common task mentioned in this list) is pretty easy without it:

    our $constant; *constant=\"this string is a constant";

    Which might not be self documenting, but it solves 99% of the problem domain in a way that doesnt require modules and should work everywhere.

    ---
    $world=~s/war/peace/g

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://559456]
Approved by planetscape
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (12)
As of 2014-09-22 16:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (198 votes), past polls