Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

use constant; RHE of solo confusing in list

by perl-diddler (Chaplain)
on Dec 06, 2019 at 02:46 UTC ( [id://11109717]=perlquestion: print w/replies, xml ) Need Help??

perl-diddler has asked for the wisdom of the Perl Monks concerning the following question:

I ran into this, and quickly took the path of least resistance, but had something like this:
use constant { zed => 0, one => 1, repos => (qw(oss non-oss debug)), two => 2, }; #output: Constant name 'non-oss' has invalid characters at -e line 3. BEGIN failed--compilation aborted at -e line 7.
Grumble. So I changed it:
tperl use constant { zed=>0, one=>1, two=>2, }; use constant repos=>(qw(oss non-oss debug)); '
Later when I saw this section again, I forgot why I split it...and tried combining it again with same results. Tried breaking things apart, but not seeing the diffs visualized:
> tperl # (alias tperl='perl -I/home/law/bin/lib -we'\''use strict; us +e P;') our $k; BEGIN{our $k={ zed => 0, one => 1, repos => [qw(oss non-oss debug)], two => 2, };} use constant $k; use constant repos2=>(qw(oss non-oss));'
Had to put assignment to k in BEGIN block for use-constants to see its value. But now no errors, but feeling uneasy about the result, I added some P statement to show me the structure(s):
tperl our $k; BEGIN{our $k={ zed => 0, one => 1, repos => [qw(oss non-oss debug)], two => 2, };} P "k=%s", $k; use constant $k; use constant repos2=>(qw(oss non-oss debug)); P "repos=%s", [repos]; P "repos2=%s", [repos2];' #output: k={one=>1, two=>2, zed=>0, repos=>["oss", "non-oss", "debug"]} repos=[["oss", "non-oss", "debug"]] repos2=["oss", "non-oss"]
Definitely a problem -- in this "solution"sic. Repos isn't a list, but a ref to a list. Grrr. Tried putting an array around the list:
repos => @{[qw(oss non-oss debug)]},
But then, fail:
Constant name 'non-oss' has invalid characters at -e line 10. BEGIN failed--compilation aborted at -e line 10.
I should just give up -- not worth the hassle, but does anyone see an easy way to combine these two constant definitions so that 1 statement will suffice for 2? Don't waste too much time...since I'll have already gone to the separate definition to move on, but sure seems a somewhat quirky situation, where because the definition in 1 def results in repos+defintion being combined with the outer list (because it is a list within a list, ala this mistake:
my ($x,$y) = (qw(1 2 3), qw(4 5 6));
Which we'd more quickly recognize as a problem if it was written:
my ($x,$y) = ( (1,2,3), (4,5,6));
Which most would see as a standard list-flattening gotcha. Which I skimmed over when I tried to combine my constant statements due to thinking that "qw" somehow would group them... Bzzzt. Anyway, Just don't see a safe & easy way to combine the definitions. Counterpoint?

Thanks!

Replies are listed 'Best First'.
Re: use constant; RHE of solo confusing in list
by AnomalousMonk (Archbishop) on Dec 06, 2019 at 03:37 UTC

    In

    use constant { zed => 0, one => 1, repos => (qw(oss non-oss debug)), two => 2, };
    the
    { zed => 0, one => 1, repos => (qw(oss non-oss debug)), two => 2, }
    part is actually an anonymous hash constructor that passes its value (a hash reference) to the constant pragma for further processing. So this hash has to be something sensible, and
    c:\@Work\Perl\monks>perl -wMstrict -MData::Dumper -le "print Dumper { zed => 0, one => 1, repos => (qw(oss non-oss debug)), two => 2, }; " $VAR1 = { 'non-oss' => 'debug', 'repos' => 'oss', 'one' => 1, 'zed' => 0, 'two' => 2 };
    ain't it. As you can see,  'non-oss' ends up as a key with  'debug' as its value because  qw(oss non-oss debug) is just a flattened list within the constructor.

    So no, you can't use the  { ... } version of constant as you initially wished because a valid hash must be built first.

    The  use constant repos2 => qw(oss non-oss); version works because the  qw() expression is what the  repos2 function created by constant is built to return. (Update: constant distinguishes between this syntax and the  { ... } hash syntax by virtue of the type of the first argument passed to it.

    c:\@Work\Perl\monks>perl -wMstrict -le "use constant [ qw(a b c d) ]; " Invalid reference type 'ARRAY' not 'HASH' at -e line 1 BEGIN failed--compilation aborted at -e line 1. c:\@Work\Perl\monks>perl -wMstrict -le "use constant qw(A b c d); print A; " bcd
    )


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

Re: use constant; RHE of solo confusing in list
by ikegami (Patriarch) on Dec 06, 2019 at 05:32 UTC

    All parens do is change precedence.[1]

    my @a = ('a', 'b', 'c');
    is only written that way because
    my @a = 'a', 'b', 'c';
    means
    ( my @a = 'a' ), 'b', 'c';

    That's why

    my @a = ( 1..4 );

    is just a weird way of writing

    my @a = 1..4;

    That means that

    use constant { zed => 0, one => 1, repos => (qw(oss non-oss debug)), two => 2, };

    is a weird way of writing

    use constant { zed => 0, one => 1, repos => 'oss', 'non-oss' => 'debug', two => 2, };

    (Same goes when using repos => @{[qw(oss non-oss debug)]}.)

    There's no way to support constants that represent more than one scalar (list use constant FOO => "a", "b";) when passing hash reference because adding support for that would have made the syntax insanely complicated.


    1. Two exceptions:

      • They can affect whether an assignment is a scalar assignment operator or a list assignment operator as described here.

      • () is the stub operator, an expression that evaluates to 0 scalars in list context and undef in scalar context.

Re: use constant; RHE of solo confusing in list
by pryrt (Abbot) on Dec 06, 2019 at 15:51 UTC
    Later when I saw this section again, I forgot why I split it...

    There's an easy fix to that. Now that you've seen from AnomalousMonk's and ikegami's replies why

    use constant { zed=>0, one=>1, two=>2, }; use constant repos=>(qw(oss non-oss debug));
    was required rather than having repos defined in the same anonymous-hash, all you have to do is change that to
    use constant { zed=>0, one=>1, two=>2, }; use constant repos=>(qw(oss non-oss debug)); # NOTE to future self: ca +nnot be in the `use constant { ... }`: # because an array cannot be the value for a key in an anonymous h +ash; # to create a constant array, it has to be in a separate `use cons +tant` line; # do not try to optimize this back into the `use constant {...}` b +ecause it won't work! # Really, I mean it!
    (though feel free to use your own commenting style)

      Yep! Comments added. I hate comments, cuz they can become out-of-date and/or separated from the code. But right above repos (repotypes):
      # do not combine Repotypes w/constants above: get list-squashing effec +t;
      Sigh...Oh well...
        separated from the code

        hence at least starting the comment on the same line, which lessens the chances of it getting separated. I originally was going to post it as a single-line comment, but it was huge that way, so I separated it for easier reading in the post.

Re: use constant; RHE of solo confusing in list
by Anonymous Monk on Dec 06, 2019 at 03:27 UTC

    What?

    use Data::Dump qw/ dd /; use constant { a => 1, b => 2, c => [qw/ d e f /] }; dd a; dd b; dd c; __END__ 1 2 ["d", "e", "f"]
Re: use constant; RHE of solo confusing in list
by Anonymous Monk on Dec 06, 2019 at 03:20 UTC

    Counterpoint?

    Abandon your peeves

    or

    Be a programmer and cater to your peeves

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (3)
As of 2024-04-24 19:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found