http://www.perlmonks.org?node_id=1023304

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

Hi, I have to create many lists of lists such as @nametape =( "24", "101" "25", "102" "23", "103" ) Is there a way to use the qw() function here to avoid typing all the quotes and commas

Replies are listed 'Best First'.
Re: qw() and lists of lists
by chromatic (Archbishop) on Mar 13, 2013 at 22:01 UTC
    my @nametape = ( [qw( 24 101 )], [qw( 25 102 )], [qw( 23 103 )], );

    Note three things, though:

    • You don't need the quotes either way, because these are valid numeric literals.
    • You do need the square brackets and trailing commas, because...
    • ... there's no such thing as a lit of lists. Lists never nest. I know—it's a nitpicky argument about definitions, but the documentation uses these words very precisely, so you'll avoid at least some confusion if you get in the habit of referring to the different entities known as "list" and "array" in the same way the documentation does.

    Improve your skills with Modern Perl: the free book.

      there's no such thing as a list of lists. Lists never nest.

      List literals never nest, a list of lists is an array of arrays

        Can you make a non-literal list of lists which doesn't nest?

        List literals can be nested:

        (1,(2,3,(4,5)),6,7)

        List operators can be nested:

        >perl -MO=Concise -e"@a=(1,(2,3,(4,5)),6,7)" j <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 i <2> aassign[t3] vKS ->j - <1> ex-list lKP ->f 3 <0> pushmark s ->4 4 <$> const[IV 1] s ->5 c <@> list lKP ->d <-- This list... 5 <0> pushmark s ->6 6 <$> const[IV 2] s ->7 7 <$> const[IV 3] s ->8 b <@> list lKP ->c <-- ...has a list for operand 8 <0> pushmark s ->9 9 <$> const[IV 4] s ->a a <$> const[IV 5] s ->b d <$> const[IV 6] s ->e e <$> const[IV 7] s ->f - <1> ex-list lK ->i f <0> pushmark s ->g h <1> rv2av[t2] lKRM*/1 ->i g <#> gv[*a] s ->h -e syntax OK

        List values can't be nested:

        >perl -E"say for (1,(2,3,(4,5)),6,7)" 1 2 3 4 5 6 7
Re: qw() and lists of lists
by tobyink (Canon) on Mar 13, 2013 at 22:29 UTC

    You may like Syntax::Feature::Qwa, but it's a pretty heavy dependency unless you're defining a lot of arrayrefs, and really hate typing square brackets.

    use 5.010; use strict; use warnings; use syntax 'qwa'; use Data::Dumper; my @nametape = ( qwa( 24 101 ), qwa( 25 102 ), qwa( 23 103 ), ); print Dumper \@nametape;

    If the arrayrefs are just numbers, then map and split might be your friends:

    use 5.010; use strict; use warnings; use Data::Dumper; my @nametape = map [split ":"] => qw( 24:101 25:102 23:103 ); print Dumper \@nametape;
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: qw() and lists of lists
by davido (Cardinal) on Mar 13, 2013 at 22:07 UTC

    One way is with pairwise.

    use List::MoreUtils qw( pairwise ); my @nametape = pairwise{ [ $a, $b ] } qw( 24 101 25 102 23 103 );

    Update, correction: pairwise accepts a block and two lists. Doh!

    What I was really after was the natatime function (also in List::MoreUtils):

    use List::MoreUtils qw(natatime); my @list = qw( 24 101 25 102 23 103 ); my $it = natatime 2, @list; my @pairs; while ( my @vals = $it->() ) { push @pairs, \@vals; }

    But frankly, the premise bugs me. It seems silly to jump through coding hoops and a runtime loop just to avoid typing [ 1,2 ], into the source code, in favor of qw( ... ). It doesn't improve code clarity, and doesn't improve code efficiency.

    Thanks kcott for noticing and pointing out to me my mistakes. My defense: The two year old was throwing a fit while I typed the original solution. I think a screaming 2-year-old is probably more of a cognitive impairment than a few stiff drinks... but since I don't drink I'm probably not qualified to make the comparison.


    Dave

Re: qw() and lists of lists
by NetWallah (Canon) on Mar 13, 2013 at 22:29 UTC
    It is more compact/convenient to generate the list using List::AllUtils "natatime":
    >perl -MList::AllUtils -MData::Dumper -E " $it= List::AllUtils::nata time(2,@ARGV); push @zz,[@x] while @x= $it->(); print Dumper \@zz" 4 +56 32 4 7 fd dffg234 2323 23
    produces:
    $VAR1 = [ [ '4', '56' ], [ '32', '4' ], .... <snip> ....
    Update: I just noticed davido's post on pairwise - It does not pass syntax on my computer.

    I am under the impression that "pairwise" requires 2 arrays, so I chose "natatime" instead.

                 "I'm fairly sure if they took porn off the Internet, there'd only be one website left, and it'd be called 'Bring Back the Porn!'"
            -- Dr. Cox, Scrubs

Re: qw() and lists of lists
by almoodie (Initiate) on Mar 13, 2013 at 22:42 UTC
      Hi, Repost correction !!!!!!!!!!!!!!!!! So the simplest manual typing method would be:
      @nametape =( [24, 101], [25, 102], [23, 103], [21, 104], [26, 105], );