Guildenstern has asked for the wisdom of the Perl Monks concerning the following question:

I was doing some research on using Win32::FileOp for this thread, and I noticed while looking through the source that all of the constant values are inplemented as subs - e.g: sub FO_MOVE     () { 0x01 }
In the module I've written, all of my similar constant declarations were with use constant..., like this:
use constant PROCESSOR_INTEL_386 => 386;
I can see that defining constants as subs avoids reliance on constant, but isn't that something that's pretty standard with a Perl distribution? Are there other issues here or tradeoffs that are worth knowing?

Guildenstern
Negaterd character class uber alles!

Replies are listed 'Best First'.
Re: What's the Right Way to declare constants in packages?
by Adam (Vicar) on Oct 27, 2000 at 20:16 UTC
    The real trade off is that constants declared as subs are, well, subs. They aren't scalars, you can't put them in strings and such. The real gain though, is that they are inlined. So if you say:
    use strict; #DUH! use constant SWITCH => 0; # off if( SWITCH ) { # do some stuff }
    The entire if(){} statement gets dropped like a comment. Pretty cool, eh?
    Note:I'm not implying that you should use that technique to embed comments, but it is very useful for things like debug-code, stubing code (for test), OS dependent code ($^O), etc....
Re: What's the Right Way to declare constants in packages?
by AgentM (Curate) on Oct 27, 2000 at 20:08 UTC
    Older Perl versions implemented constants as subs so there was essentially no difference. Now the constants are precompiled.
    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
RE: What's the Right Way to declare constants in packages?
by mikfire (Deacon) on Nov 01, 2000 at 00:11 UTC
    Both forms are correct. If you crack open constant.pm, you will discover all it does is play some neat games with constant functions.

    An optimization in the Perl compiler recognizes does some special optimizations when a function is declared with a () prototype is not called with either a do or an &. If after all the smoke and magic the function returns a constant value, this value will be substituted directly into the code, instead of incurring the subroutine call overhead each time.

    I have done both - there are times when use constant is more useful ( standardized, don't have to think how it works, etc ) and there are times when declaring you own subroutines is useful ( lots of them, defining all your constants in one file, etc ).

    For more information, read perldoc perlsub and search on the string 'Constant Functions'

    mikfire

You can do string interpolation on sub output
by princepawn (Parson) on Oct 27, 2000 at 22:23 UTC
    'twas bespoken by Adam:  The real trade off is that constants declared as subs are, well, subs. They aren't scalars, you can't put them in strings and such

    But we can in fact place sub output in strings:

    sub pi { 'apple 3.1415936535897532'; } my $str = "I like breadnbutter. I like toasted ham. I like @{[pi]}"; print $str, $/;

    output

    I like bread and butter. I like toast and jam. I like pi

    Acknickulous Acknowledgements

    runrig and fastolfe actually coached me through this... and I think merlyn conceived that this should be a part of Perl so we owe him a big slap on the back.
      First off, your program,
      sub pi { 'apple 3.1415936535897532'; } my $str = "I like breadnbutter. I like toasted ham. I like @{[pi]}"; print $str, $/;
      When run, prints:
      I like breadnbutter. I like toasted ham. I like apple 3.14159365358975 +32
      not
      I like bread and butter. I like toast and jam. I like pi
      Which is what your post said. But I think that's what you meant, so its ok. My real problem is that you are jumping through several hoops to do something that is trivial with a scalar:
      sub pi { 'apple 3.1415936535897532'; } my $Nov_Pi = 'pumpkin pie'; # Make anonymous array ref with output of pi(). Then de-ref the array. my $str = "I like breadnbutter. I like toasted ham. I like @{[pi]}"; # Concatenate a scalar. my $Nov_str = "I also like $Nov_Pi"; print $str, $/, $Nov_str, $/;
      Note that you are far better off breaking out of the string instead of interpolating in this fashion, because Perl has to put your subroutine's output into an array reference, de-reference it, then string-ify it. It's far more efficient to do this:
      my $str = "I like ... I like " . pi;

      ObMathNitpick: Not that it has much bearing on your script, but the 'apple pi' pun would be better as 'apple 3.1415926535897932...'

        3.14159265358979323846264338327950288419716939 937510582097494459230781640628620899862803482 534211706798214808651328230664709384460955058 ...

        Courtesy of www.wpdpi.com