[Melbourne-pm] map -- with an iterator

Toby Corkindale toby.corkindale at strategicdata.com.au
Thu Apr 22 00:39:32 PDT 2010


On 22/04/10 16:54, Sam Watkins wrote:
> On Thu, Apr 22, 2010 at 03:59:23PM +1000, Toby Corkindale wrote:
>> Hey all,
>> You're all familiar with the map operator, used like so:
>>
>>    my @results = map { transform $_ } @input;
>>
>>
>> However I often find that instead of @input, I have $iterator,
>> where $iterator is an object supporting a ->next method.
>>
>>
>> What I would like to be able to do is something like:
>>    my @results = map { transform $_ } $iterator;
>> and then have map walk through my iterator for me.
>
> ok, how about this:
>
>      #!/usr/bin/perl
>      use strict; use warnings;
>
>      sub mapit (&$) {
>          my ($sub, $it) = @_;
>          my @out;
>          while (defined (my $x = $it->next)) {
>              push @out, $x;
>          }
>          return @out;
>      }
>
>      my $it = It->new;
>
>      my @out = mapit { $_ . "foo" } $it;
>
>      print "@out\n";
>
>      package It;
>
>      sub new {
>          return bless {x=>5};
>      }
>
>      sub next {
>          my ($self) = @_;
>          my $x = $self->{x}--;
>          return $x>= 0 ? $x : undef;
>      }


Ah, the idea of having the iterator-aware map was to prevent creating a 
temporary array containing everything in the iterator.

Eg. Say that the iterator returns a 10 Mbyte object every time you call 
->next, and that you have one million items to get through.

If you have to put them all into a temporary @out array first, then you 
chew up vast amounts of ram. Whereas if your iterator/map combo is 
smarter, then you only use 10 Mb at a time. (If you accumulating 
results, then you'll still build up an array of results, of course. But 
it might be a lot smaller.. or at the very least, it's only one copy of 
the results, not two.)

So, currently one tends to do:
while (my $item = $iterator->next) {
   do_stuff_to($item);
}

But it would be nice, syntactically, to say
$iterator->foreach(sub { do_stuff($_) });



More information about the Melbourne-pm mailing list