Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Re: 2*pi*$r -- constant function without prototype

by ikegami (Patriarch)
on May 01, 2008 at 10:27 UTC ( #683901=note: print w/replies, xml ) Need Help??

in reply to 2*pi*$r -- constant function without prototype

Omitting parens around arguments is fraught with peril. You've just encountered yet another situation where the parser gets "confused".

It's my understanding that the constants created using constant and using functions with the empty prototype are not identical anymore, and that using constant is the recommended method.

  • Comment on Re: 2*pi*$r -- constant function without prototype

Replies are listed 'Best First'.
Re^2: 2*pi*$r -- constant function without prototype
by why_bird (Pilgrim) on May 01, 2008 at 10:50 UTC

    I thought the recommended advice was to use Readonly instead of use constant. Is this wrong, or if not, could you explain the circumstances when you should use each one?

    Those are my principles. If you don't like them I have others.
    -- Groucho Marx

      Not sure if I would recommend Readonly over constant — at least some people have been bitten by its subtle peculiarities. As an example, see this thread.

      BTW, there's also Scalar::Readonly, which is directly manipulating the readonly-flag of scalars (instead of working with tied magic)...


      Update:  ( was only a matter of time until someone would post a benchmark, so... :)

      use strict; use warnings; use Benchmark 'cmpthese'; use Readonly; use Scalar::Readonly ':all'; use constant NL => "\012"; Readonly my $NL => "\012"; my $nl = "\012"; readonly_on($nl); my $Nl = "\012"; cmpthese 2000000 => { constant => sub { my $s = "abc".NL."def".NL."ghi"; }, constant2 => sub { my $s = "abc${\NL}def${\NL}ghi"; }, Readonly => sub { my $s = "abc${NL}def${NL}ghi"; }, ScalarRO => sub { my $s = "abc${nl}def${nl}ghi"; }, scalarRW => sub { my $s = "abc${Nl}def${Nl}ghi"; }, direct => sub { my $s = "abc\012def\012ghi"; }, }; __END__ Rate Readonly constant2 scalarRW ScalarRO constant + direct Readonly 77851/s -- -84% -85% -85% -96% + -96% constant2 484262/s 522% -- -5% -5% -75% + -75% scalarRW 510204/s 555% 5% -- -0% -74% + -74% ScalarRO 511509/s 557% 6% 0% -- -74% + -74% constant 1960784/s 2419% 305% 284% 283% -- + -0% direct 1960784/s 2419% 305% 284% 283% 0% + --

      (as running the benchmark multiple times suggests, differences up to around 5% are insignificant)


      BTW, I think I remember PBP somewhere saying it's not meant to be treated as a bible...

        The benchmark results vary quite much on my laptop (Perl 5.8.8, Ubuntu). Especially 'constant' and 'direct' are not identical but differ by a factor of 1/2 to 2.

        I had the idea to use Data::Dumper with Deparse = 1 on the hash to look how perl optimizes the constants:

        $VAR1 = { 'direct' => sub { my $s = "abc\ndef\nghi"; }, 'scalarRW' => sub { my $s = "abc${Nl}def${Nl}ghi"; }, 'constant' => sub { my $s = "abc\ndef\nghi"; }, 'Readonly' => sub { my $s = "abc${NL}def${NL}ghi"; }, 'constant2' => sub { my $s = qq[abc${\"\n";}def${\"\n";}ghi] +; }, 'ScalarRO' => sub { my $s = "abc${nl}def${nl}ghi"; } };
        (I removed the use warnings; use strict 'refs'; from each sub to make it easier to read).
        As you can see 'constant' is identical with 'direct' after compilation. 'constant2' still has the dereferencing and referencing included, which makes it slow. The others have the variable included and only differ on how it is accessed. Because Readonly is tied it is the slowest.
      Perl Best Practices recommends Readonly. While constants with use constant are replaced at compile time, Readonly variables are normal variables, just set read-only.
      The problem with use constant is that the constants are actual functions which don't interpolate in strings!

      I recently needed the line feed ("\012") as constant (Note: "\n" is platform dependent!).

      use Readonly; Readonly $NL => "\012"; [...] print FILE "header1${NL}header2${NL}"; use constant NL => "\012"; [...] print FILE "header1" . NL . "header2" . NL;
      The speed penalty for Readonly is not meaningful in my case. However if you have large calculations which only dependent on constants, maybe inside a loop, then use constant is better because perl can optimise it at compile time.

        As long as your going to use ${} to interpolate vars into strings, which is generally a good idea. Then you can use constants in a similar way with a single extra '\' character:

        use constant NL => "\012";; print "fred${\NL}bill${\NL}";; fred bill

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://683901]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2022-12-10 02:51 GMT
Find Nodes?
    Voting Booth?

    No recent polls found