Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

"Nonliteral literal" is just an expression.

by rir (Vicar)
on Sep 24, 2019 at 04:40 UTC ( #11106621=perlmeditation: print w/replies, xml ) Need Help??

With AoAs something like:
my $ar = [ [ 'HEAD_goes_here', 'BODY_here' ], [ 'FOOT', 'FOOT', 'FOOT', 'FOOT' ] ];
written as a template with the literals as documentation. After the not-finding and the not-thinking, I wrote a sub to walk AoAs and extract the references to the scalar elements. Doing it by hand, one might write:
my $scalars_flattened = [ \$ar->[0][0], \$ar->[0][1], \$ar->[1][0], \$ar->[1][1], \$ar->[1][2], \$ar->[1][3] ];
Its gist:
my @flat = @{$_[0]}; while ( List::Util::any { 'ARRAY' eq ref $_ } @flat ) { @flat = map { 'ARRAY' eq ref $_ ? \(@$_) : \$_ } @flat; @flat = map { 'REF' eq ref $_ ? $$_ : $_ } @flat; }
Fortunately only in testing did I find the less helpfully shaped templates like:
$ar = [ 'HEAD', 'BODY', [ 'FOOT', 'FOOT', 'FOOT', 'FOOT'], ];
I would die if I had one like that.

Be well,
rir

Replies are listed 'Best First'.
Re: "Nonliteral literal" is just an expression.
by choroba (Archbishop) on Sep 24, 2019 at 10:04 UTC
    This calls for recursion.
    #!/usr/bin/perl use warnings; use strict; use List::Util qw{ any }; sub flatten { my ($struct) = @_; if (ref [] eq ref $struct) { return map flatten($_), @$struct } elsif (ref \\"" eq ref $struct) { return $$struct } else { return \$struct } } use Test::More tests => 2; my $ar = [ [ 'HEAD_goes_here', 'BODY_here' ], [ 'FOOT', 'FOOT', 'FOOT', 'FOOT' ] ]; my @flat = @$ar; while ( any { ref [] eq ref $_ } @flat ) { @flat = map { ref [] eq ref $_ ? \(@$_) : \$_ } @flat; @flat = map { ref \\"" eq ref $_ ? $$_ : $_ } @flat; } is_deeply \@flat, [map \$_, qw[ HEAD_goes_here BODY_here FOOT FOOT FOOT FOOT ] ]; is_deeply [flatten($ar)], \@flat;

    What's wrong with the "less helpful" template? Both approaches return the same result.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      What's wrong with the "less helpful" template?

      That is the interesting part. And it surprises me that I have never been caught by this in my years of occasional programming. I am still chewing on that aspect.

      Both approaches return the same result.

      Not quite, your tests are flawed. I wanted references to the same memory objects ("thingie" is out of style?) so running @flat through both your and my code is suspect on its face. When I comment out the while loop I don't get a happy result.

      On a side note: In the "not-thinking" part I started on a recursive solution; when I hit some snags and applied some thought map seemed a clear win. I should study the methods to go from one to the other: iter. vs. recurs.

      Using a shorter array:

      my $ar = [ [ 'a', ], [ 'b, 'c', ], ]; my $flat = flat( $ar ); print Dumper $ar, $flat;
      should yield:
      $VAR1 = [ [ 'a' ], [ 'b', 'c' ] ]; $VAR2 = [ \$VAR1->[0][0], \$VAR1->[1][0], \$VAR1->[1][1] ];
        Ah, now I understand! A small change in the flatten subroutine should fix that.
        sub flatten { my ($struct) = @_; if (ref [] eq ref $struct) { return map flatten($_), @$struct } else { return \$_[0] # <- We need to use the alias, not a copy. } }
        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2020-07-12 03:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?