Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

How to interpolate CONSTANTS in Here docs?

by CoVAX (Beadle)
on Feb 11, 2015 at 21:39 UTC ( #1116399=perlquestion: print w/replies, xml ) Need Help??

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

I have some constants (defined with `use constant`) that I am desirous of using in a `here` doc. However no interpolation occurs, so the strings naming the constants literally appear instead of their values.

What I have resorted to is: assigning variables the values of the constants, and using the variable names in the here doc. Is there a better way to accomplish the desired behavior?

use constant { OUT_DIR => 'out', OUT_FIELDSEP => '=', OUT_FILENAME => 'ks', OUT_SUFXSTOR => 'storable', VAL_MIN => 15, VAL_MAX => 3600, };

This does not work as intended:

print <<USAGE; This program does this and that with the OUT_DIR. The filename is OUT_FILENAME and the file suffix is OUT_SUFXSTOR. Fields are separated with the OUT_FIELDSEP character. Enter a value between VAL_MIN and VAL_MAX. USAGE

What I've resort to doing:

my $out_dir = OUT_DIR; my $out_fs = OUT_FIELDSEP; my $out_fn = OUT_FILENAME; my $out_sx = OUT_SUFXSTOR; my $valmin = VAL_MIN; my $valmax = VAL_MAX; print <<USAGE; This program does this and that with the $out_dir. The filename is $out_fn and the file suffix is $out_sx. Fields are separated with the $out_fs character. Enter a value between $valmin and $valmax. USAGE
Searched for donuts and crumpit. Found content instead.

Replies are listed 'Best First'.
Re: How to interpolate CONSTANTS in Here docs?
by BrowserUk (Pope) on Feb 11, 2015 at 21:55 UTC

    C:\test>type junk94.pl #! perl -slw use strict; use constant { OUT_DIR => 'out', OUT_FIELDSEP => '=', OUT_FILENAME => 'ks', OUT_SUFXSTOR => 'storable', VAL_MIN => 15, VAL_MAX => 3600, }; print <<USAGE; This program does this and that with the @{[OUT_DIR]}. The filename is @{[OUT_FILENAME]} and the file suffix is @{[OUT_SUFXSTOR]}. Fields are separated with the @{[OUT_FIELDSEP]} character. Enter a val +ue between @{[VAL_MIN]} and @{[VAL_MAX]}. USAGE C:\test>junk94 This program does this and that with the out. The filename is ks and the file suffix is storable. Fields are separated with the = character. Enter a value between 15 and 3600.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

      Thank you for your answer.

      I'm not understanding the @{[]} syntax, although I do recognize the array index [], the hash {}, and the array @ -- can you explain what is going on, please?

      Searched for donuts and crumpit. Found content instead.

        Anonymonk has explained the syntax; but I thought I'd add that I'm not keen on doing it that way. Personally I prefer:

        #! perl -slw use strict; use constant { OUT_DIR => 'out', OUT_FIELDSEP => '=', OUT_FILENAME => 'ks', OUT_SUFXSTOR => 'storable', VAL_MIN => 15, VAL_MAX => 3600, }; printf <<USAGE, OUT_DIR, OUT_FILENAME, OUT_SUFXSTOR, OUT_FIELDSEP, VAL +_MIN, VAL_MAX; This program does this and that with the %s. The filename is %s and the file suffix is %s. Fields are separated with the %s character. Enter a value between %s and %s. USAGE

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        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". I'm with torvalds on this
        In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

        [...] builds a reference to an anonymous array, which is in turn de-referenced by @{...}. It's roundabout, but necessary in this case because the constants built by constant are actually functions, like sub OUT_DIR () { 'out' }, and a function call like OUT_DIR() (or OUT_DIR) isn't interpolated in strings, while scalars ($foo) and arrays (@bar) are, including dereferenced arrayrefs (@{$arrayref} - see e.g. Using References).

        I'm not understanding the @{[]} syntax, although I do recognize the array index [], the hash {}, and the array @ -- can you explain what is going on, please?

        The array index isn't an array index, the hash isn't a hash.
        @{ } dereferences an array reference. ${ } dereferences a scalar reference. [ ] constructs an array refrence, \ constructs a scalar reference. So, instead of writing

        This program does this and that with the @{[OUT_DIR]}. The filename is @{[OUT_FILENAME]} and the file suffix is @{[OUT_SUFXSTOR]}. Fields are separated with the @{[OUT_FIELDSEP]} character. Enter a val +ue between @{[VAL_MIN]} and @{[VAL_MAX]}.

        as in BrowserUk's example, you could also write

        This program does this and that with the ${\OUT_DIR}. The filename is ${\OUT_FILENAME} and the file suffix is ${\OUT_SUFXSTOR}. Fields are separated with the ${\OUT_FIELDSEP} character. Enter a valu +e between ${\VAL_MIN} and ${\VAL_MAX}.

        The reference implementation in perl is the author's way of introducing ásbestos gélōs into the language, great fun and a good opportunity to distinguish yourself with expertise, once you grok cause and syntax.

        Quick, what does ~@~ mean?

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

        If you spread it out,

        "foo @{[ F ]} bar"

        you get

        my @anon_array = F; my $anon_ref = \@anon_array; "foo @{ $anon_ref } bar"

        As you can see,

        • @BLOCK (@{ STATEMENTS }) is an array dereference, not "a hash".

        • [ LIST ] is an array constructor, not "an array index". It creates an array, assigns the result of LIST, and returns a reference to that array.

Re: How to interpolate CONSTANTS in Here docs?
by AnomalousMonk (Bishop) on Feb 11, 2015 at 21:49 UTC

    Interpolation rules for here-docs are the same as for double- and single-quoted strings (double in the OPed example), so one way:

    c:\@Work\Perl>perl -wMstrict -le "use constant OUT_SUFXSTOR => 'storable'; ;; my $str = qq{The file suffix is ${ \ OUT_SUFXSTOR}.}; print qq{'$str'}; " 'The file suffix is storable.'

    Update: Then there's also:

    c:\@Work\Perl>perl -wMstrict -le "use constant OUT_SUFXSTOR => 'storable'; ;; my $str = qq{The file suffix is @{[ OUT_SUFXSTOR ]}.}; print qq{'$str'}; " 'The file suffix is storable.'


    Give a man a fish:  <%-(-(-(-<

Re: How to interpolate CONSTANTS in Here docs?
by Anonymous Monk on Feb 11, 2015 at 23:19 UTC

    It might be noteworthy that Conway's Perl Best Practices recommends against constant, partly for exactly the reason you're having trouble (they don't interpolate) - a similar issue arises when they're used in hashes, as documented in "Caveats" in constant.

    The suggested alternative is Readonly, but it has a few bugs, and I've found Readonly is not really necessary if you just stick to not modifying variables whose names are in $ALL_CAPS (people with a more defensive coding philosophy might disagree).

    Of course you are free to disagree with PBP on this point and use constant, in which case I think the solutions given by AnomalousMonk and BrowserUk above are preferable to the following, because they catch errors due to typos in the constant names better. But since this is Perl, and in the spirit of TIMTOWTDI, here's another solution:

    my $USAGE=<<'USAGE'; Fields are separated with the OUT_FIELDSEP character. Enter a value between VAL_MIN and VAL_MAX. USAGE $USAGE=~s/\b\Q$_\E\b/$_/ee for qw/ OUT_FIELDSEP VAL_MIN VAL_MAX /;
      It might be noteworthy that Conway's Perl Best Practices recommends against constant,

      Grrr. That damn book has done infinitely more harm than good. (As predicted!)

      It completely misses the point of constant; namely that it works with Perl to optimise your code.

      Because constants are defined as invariant subroutines, Perl can optimise away whole chunks of code at compile time:

      C:\test>perl -MO=Deparse -Mconstant=DEBUG,1 -le"print 'hi'; DEBUG and +print 'here'; print 'bye'" BEGIN { $/ = "\n"; $\ = "\n"; } use constant (split(/,/, 'DEBUG,1', 0)); print 'hi'; print 'here'; ## When DEBUG is defined; it doesn't need to be teste +d for at runtime. (No conditional!) print 'bye'; -e syntax OK C:\test>perl -MO=Deparse -Mconstant=DEBUG,0 -le"print 'hi'; DEBUG and +print 'here'; print 'bye'" BEGIN { $/ = "\n"; $\ = "\n"; } use constant (split(/,/, 'DEBUG,0', 0)); print 'hi'; '???'; ## And when it's not; both the conditional and the cod +e it controls are simply optimised away. print 'bye'; -e syntax OK

      Write-once variables are a piss poor substitute; an anathema to Perl; and an abomination.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      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". I'm with torvalds on this
      In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
        That damn book has done infinitely more harm than good. (As predicted!)

        I can't gainsay; and I wouldn't if I could.

        Write-once variables are a piss poor substitute; an anathema to Perl; and an abomination.

        True, true and true. We would upvote all of this if I were four of me.

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      FFS, please report these 'bugs' on the tracker. I've cleared up all the valid issues and sped it up to the point that Readonly::XS can be withered. If you've found something new, the only way to get it fixed is to report it.
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2020-09-25 16:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If at first I don’t succeed, I …










    Results (138 votes). Check out past polls.

    Notices?