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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |