... inside first anonymous block parameter array at top is ARRAY(0x5600d58ded50) R3 default is R3 data is4 parameter array at bottom is ARRAY(0x5600d58ded50) R3 data is 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 12 13 14 15 16 17 18 19 20 51 52 53 54 55 56 57 58 59 60 leaving getsubset 11 12 13 14 15 16 17 18 19 20 ok 19 11 12 13 14 15 16 17 18 19 20 11 12 13 14 15 66 17 18 19 20 exiting first anonymous block ---------- 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 12 13 14 15 66 17 18 19 20 51 52 53 54 55 56 57 58 59 60 ---------- parameter array at top is ARRAY(0x5600d58ded50) C2 default is C2 data is4 parameter array at bottom is ARRAY(0x5600d58ded50) C2 data is 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 12 13 14 15 66 17 18 19 20 51 52 53 54 55 56 57 58 59 60 leaving getsubset 2 b 12 52 ok 20 2 b 21 52 exit 2nd ---------- 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 21 13 14 15 66 17 18 19 20 51 52 53 54 55 56 57 58 59 60 ---------- parameter array at top is ARRAY(0x5600d58ded50) R4C2 default is R4C2 data is4 parameter array at bottom is ARRAY(0x5600d58ded50) R4C2 data is 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 21 13 14 15 66 17 18 19 20 51 52 53 54 55 56 57 58 59 60 leaving getsubset 52 ok 21 end 3rd ---------- 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 21 13 14 15 66 17 18 19 20 51 42 53 54 55 56 57 58 59 60 ---------- parameter array at top is ARRAY(0x5600d58ded50) R2C5:R4C8 default is R2C5:R4C8 data is4 parameter array at bottom is ARRAY(0x5600d58ded50) R2C5:R4C8 data is 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 21 13 14 15 66 17 18 19 20 51 42 53 54 55 56 57 58 59 60 leaving getsubset e f g h 15 66 17 18 55 56 57 58 ok 22 added 5 to a value ---------- 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 21 13 14 15 66 22 18 19 20 51 42 53 54 55 56 57 58 59 60 ---------- parameter array at top is ARRAY(0x5600d58ded50) C8:Cn default is C8:Cn data is4 parameter array at bottom is ARRAY(0x5600d58ded50) C8:Cn data is 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j 11 21 13 14 15 66 22 18 19 20 51 42 53 54 55 56 57 58 59 60 leaving getsubset 8 9 10 h i j 18 19 20 58 59 60 ok 23 substitutes X ---------- 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i X 11 21 13 14 15 66 22 18 19 20 51 42 53 54 55 56 57 58 59 60 ---------- parameter array at top is ARRAY(0x5600d58ded50) R4 default is R4 data is4 parameter array at bottom is ARRAY(0x5600d58ded50) R4 data is 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i X 11 21 13 14 15 66 22 18 19 20 51 42 53 54 55 56 57 58 59 60 leaving getsubset 51 42 53 54 55 56 57 58 59 60 ok 24 ---------- 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i X 11 21 13 14 15 66 22 18 19 20 51 42 53 54 55 56 57 58 59 60 ---------- ok 25 ## end abridged output begin source $ cat 2.da.pl #!/usr/bin/perl -w use 5.011; use Carp; use Data::Alias 'alias'; use Data::Dumper; sub print_aoa { use warnings; use 5.011; my $a = shift; my @array = @$a; for my $row (@array) { print join( " ", @{$row} ), "\n"; } return $a; } sub rangeparse { local $_ = shift; say "default is $_"; my @o; # [ row1,col1, row2,col2 ] (-1 = last row/col) if ( @o = /\AR([0-9]+|n)C([0-9]+|n):R([0-9]+|n)C([0-9]+|n)\z/ ) { } elsif (/\AR([0-9]+|n):R([0-9]+|n)\z/) { @o = ( $1, 1, $2, -1 ) } elsif (/\AC([0-9]+|n):C([0-9]+|n)\z/) { @o = ( 1, $1, -1, $2 ) } elsif (/\AR([0-9]+|n)C([0-9]+|n)\z/) { @o = ( $1, $2, $1, $2 ) } elsif (/\AR([0-9]+|n)\z/) { @o = ( $1, 1, $1, -1 ) } elsif (/\AC([0-9]+|n)\z/) { @o = ( 1, $1, -1, $1 ) } else { croak "failed to parse '$_'" } $_ eq 'n' and $_ = -1 for @o; return \@o; } sub getsubset { my ( $data, $range ) = @_; say "parameter array at top is @_"; my $cols = @{ $$data[0] }; @$_ == $cols or croak "data not rectangular" for @$data; $range = rangeparse($range) unless ref $range eq 'ARRAY'; @$range == 4 or croak "bad size of range"; say "data is", 0 + @$data; my @max = ( 0 + @$data, $cols ) x 2; # say "max is @max"; max is 4 10 4 10 for my $i ( 0 .. 3 ) { $$range[$i] = $max[$i] if $$range[$i] < 0; croak "index $i out of range" if $$range[$i] < 1 || $$range[$i] > $max[$i]; } croak "bad rows $$range[0]-$$range[2]" if $$range[0] > $$range[2]; croak "bad cols $$range[1]-$$range[3]" if $$range[1] > $$range[3]; my @cis = $$range[1] - 1 .. $$range[3] - 1; say "parameter array at bottom is @_"; say "data is"; print_aoa($data); say "leaving getsubset"; return [ map { sub { \@_ } ->( @{ $$data[$_] }[@cis] ) } $$range[0] - 1 .. $$range[2] - 1 ]; } use Test::More tests => 25; is_deeply rangeparse("R1"), [ 1, 1, 1, -1 ]; is_deeply rangeparse("C1"), [ 1, 1, -1, 1 ]; is_deeply rangeparse("Rn"), [ -1, 1, -1, -1 ]; is_deeply rangeparse("Cn"), [ 1, -1, -1, -1 ]; is_deeply rangeparse("R4C5"), [ 4, 5, 4, 5 ]; is_deeply rangeparse("RnCn"), [ -1, -1, -1, -1 ]; is_deeply rangeparse("R2:R3"), [ 2, 1, 3, -1 ]; is_deeply rangeparse("C2:C3"), [ 1, 2, -1, 3 ]; is_deeply rangeparse("R4:Rn"), [ 4, 1, -1, -1 ]; is_deeply rangeparse("C5:Cn"), [ 1, 5, -1, -1 ]; is_deeply rangeparse("R2C3:R4C5"), [ 2, 3, 4, 5 ]; is_deeply rangeparse("R4C3:R4C3"), [ 4, 3, 4, 3 ]; is_deeply rangeparse("R5C1:R5C9"), [ 5, 1, 5, 9 ]; is_deeply rangeparse("R2C6:R11C6"), [ 2, 6, 11, 6 ]; is_deeply rangeparse("R3C1:RnC2"), [ 3, 1, -1, 2 ]; is_deeply rangeparse("R5C4:R5Cn"), [ 5, 4, 5, -1 ]; is_deeply rangeparse("RnC2:RnC5"), [ -1, 2, -1, 5 ]; is_deeply rangeparse("R3C2:RnCn"), [ 3, 2, -1, -1 ]; my $data = [ [ 1 .. 10 ], [ 'a' .. 'j' ], [ 11 .. 20 ], [ 51 .. 60 ] ]; { say "inside first anonymous block"; my $subset = getsubset( $data, "R3" ); print_aoa $subset; is_deeply $subset, [ [ 11 .. 20 ] ]; print_aoa $subset; $subset->[0][5] = 66; print_aoa $subset; say "exiting first anonymous block"; } say "----------"; print_aoa $data; say "----------"; { my $subset = getsubset( $data, "C2" ); print_aoa $subset; is_deeply $subset, [ [2], ['b'], [12], [52] ]; $subset->[2][0] = 21; print_aoa $subset; say "exit 2nd"; } say "----------"; print_aoa $data; say "----------"; { my $subset = getsubset( $data, "R4C2" ); print_aoa $subset; is_deeply $subset, [ [52] ]; $subset->[0][0] = 42; say "end 3rd"; } say "----------"; print_aoa $data; say "----------"; { my $subset = getsubset( $data, "R2C5:R4C8" ); print_aoa $subset; is_deeply $subset, [ [ 'e' .. 'h' ], [ 15, 66, 17, 18 ], [ 55, 56, 57, 58 ] ]; $subset->[1][2] += 5; say "added 5 to a value"; } say "----------"; print_aoa $data; say "----------"; { my $subset = getsubset( $data, "C8:Cn" ); print_aoa $subset; is_deeply $subset, [ [ 8 .. 10 ], [ 'h' .. 'j' ], [ 18 .. 20 ], [ 58 .. 60 ] ]; $subset->[1][2] = 'X'; say "substitutes X"; } say "----------"; print_aoa $data; say "----------"; { my $subset = getsubset( $data, "R4" ); print_aoa $subset; is_deeply $subset, [ [ 51, 42, 53, 54, 55, 56, 57, 58, 59, 60 ] ]; #$subset->[0][0] = 'M'; #say "substitutes M"; } say "----------"; print_aoa $data; say "----------"; is_deeply $data, [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], [qw/a b c d e f g h i X/], [ 11, 21, 13, 14, 15, 66, 22, 18, 19, 20 ], [ 51, 42, 53, 54, 55, 56, 57, 58, 59, 60 ] ]; $ #### return [ map { sub { \@_ } ->( @{ $$data[$_] }[@cis] ) } $$range[0] - 1 .. $$range[2] - 1 ]; #### return [ map { arr_alias @$_[ $cols->[0] .. $cols->[1] ] # x-slice } @$data[ $rows->[0] .. $rows->[1] ] # y-slice ];