[Chicago-talk] Array slices

Jim Thomason jim at jimandkoka.com
Thu Nov 9 11:08:37 PST 2006

```I ran smack into this issue while working on a different problem and
did come up with a solution to do it with no iterating. But, it does
require some advance set up to work.

#!/usr/bin/perl

my %slicer_dispatch = ();
sub slicer_maker {
my \$num_arrays = shift;

return \$slicer_dispatch{\$num_arrays} if \$slicer_dispatch{\$num_arrays};

my \$sliced_list = join(', ', map {'\$_[' . \$_ . ']->[\$idx]'}
(0..\$num_arrays - 1));

return \$slicer_dispatch{\$num_arrays} = eval qq[
sub {
my \\$idx = shift;
return (\$sliced_list);
}
];
}

@a = ([1,2],[3,4],[5,6]);

my \$slicer = slicer_maker(scalar @a);
my @results = \$slicer->(1, @a);

print "@results\n";   # prints 2 4 6

Caveats -
* This is only cost effective if you're slicing many times. Just
grabbing out the "2" element one time is faster to do in an iteration.
* You need to build a new slicer function for each number of arguments
you have. New slicer function if you're using 3 arrays, another if
you're using 5, and so on.
* I haven't benchmarked it, but the performance may be...odd. I was
also working on a solution along these lines for summing arbitrary
sets of numbers an the performance was weird. An iterated summation
(\$sum += \$+ for @array) was faster than a generated function for very
small lists (< 10 elements), but got slower after that. The generated
function was then faster up until about 4,000 elements in the list,
and after that the iterated version overtook it. I'm sure there's some
sort of limit in the internals it's hitting to explain it.
* I haven't decided if needing all the different functions for various
numbers of arguments makes me feel like a C programmer for needing
'em, or a Lisp programmer for generating them. Either way, I need a
bath.
* The general technique can be applied to any operation that requires
a variable number of arguments.
* Assuming this isn't named already. I propose calling it a
"Thomasonian dynamic slice". If it proves popular, then "Grand
Thomasonian dynamic slice"

-Jim...........

On 11/5/06, Jay Strauss <me at heyjay.com> wrote:
> > Do you consider "map" to be iteration?
> >
> > Jay> For example, I'd like to create a slice out of the 2nd element of each
> > Jay> inner array, so that my result would be (2,4,6).
> >
> > Jay> @a = ([1,2],[3,4],[5,6]);
> >
> > Jay> print join @a[][1],"\n";  # doesn't work
> > Jay> print join @a[0..2][1],"\n"; #doesn't work
> >
> > my @a = ([1,2],[3,4],[5,6]);
> > my @result = map \$_->[1], @a;
> > print "@result\n";
>
> I do consider it to be an iterator.  I'm actually already using map,
> but I thought there may be some niffy syntax that would do it for me.
>
> mine looks like:  my @attributes  = map {\$_->[1] } @parm_defs;
>
> I guess I could leave off the braces, and add a comma :)
>
> Thanks
> jay
> _______________________________________________
> Chicago-talk mailing list
> Chicago-talk at pm.org
> http://mail.pm.org/mailman/listinfo/chicago-talk
>
```