my @max = ( 0 + @$data, $cols ) x 2; I'm just looking for a reference to read up on that.

See the x operator under Multiplicative Operators. I'm just using it as a shorthand for my @max = ( 0 + @$data, $cols, 0 + @$data, $cols );.

The second thing I wanted to bring up was about the parameter array. Is it the case that @_ does not change over the life of the function? Does it have intrinsic aliasing?

@_ is described in perlsub: "The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated ... Assigning to the whole array @_ removes that aliasing, and does not update any arguments." As to whether it doesn't change, that depends on what the sub does - it is not read-only. For example, shift and pop can modify @_, and in Perl versions 5.10 and older, split could clobber @_. And there are some other potentially tricky issues with @_, for example, if a sub is called with an & and no argument list, "no @_ array is set up for the subroutine: the @_ array at the time of the call is visible to subroutine instead" (also perlsub).

You use the range operator once. LanX (upthread for the curious) used it twice:

Well, actually I used it twice, note how I set up the @cis array. And yes, those two snippets of code from LanX and myself are basically equivalent. One difference is that I use 1-based indexing in the indices stored in the @$range array.

I can't see how the sausage gets made here

Ok, so here's my original code:

my @cis = $$range[1]-1 .. $$range[3]-1; return [ map { sub{\@_}->(@{$$data[$_]}[@cis]) } $$range[0]-1 .. $$range[2]-1 ]

First, let's reformat that, and instead of @$range, let me use four lexical variables corresponding to the elements of the array ($row1, $col1, $rowN, $colN), and make them 0-based instead of 1-based.

my @column_indices = $col1 .. $colN; return [ map { sub{ \@_ }->( @{ $$data[$_] }[@column_indices] ) } $row1 .. $rowN ]

Now, map can be translated into a for with push (I hope that transformation is clear?). I've also pulled out various bits of expressions into lexical variables.

my @row_indices = $row1 .. $rowN; my @column_indices = $col1 .. $colN; my @row_subset; for my $row_idx (@row_indices) { my $row = $$data[$row_idx]; # deref $data and get row my $column_subset_aliases = sub{ \@_ }->( @$row[@column_indices] # deref $row and get array slice ); push @row_subset, $column_subset_aliases; } return \@row_subset;

Now the last bit of trickery here is sub{\@_}->(...). sub {...} constructs an anonymous subroutine, which is then immediately called (via ->(...)) and with the arguments (...). The body of the sub is just \@_, which means "return a reference to @_". Because the elements of @_ are aliases to the original arguments, what we get back from the whole expression is an arrayref whose elements are aliases to the arguments. In the above code, those arguments are the elements of the array referred to by $row, which were selected by the array slice.

I hope it's at least a little bit more clear now?


In reply to Re^4: Selecting Ranges of 2-Dimensional Data by haukex
in thread Selecting Ranges of 2-Dimensional Data by haukex

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.