<?xml version="1.0" encoding="windows-1252"?>
<node id="44763" title="mapcar -- map for more than one list" created="2000-12-04 07:21:45" updated="2005-08-15 17:17:41">
<type id="1980">
snippet</type>
<author id="22609">
tye</author>
<data>
<field name="doctext">
</field>
<field name="snippetdesc">
&lt;b&gt;Update:&lt;/b&gt; Now available in several flavors as part of [cpan://Algorithm::Loops].
&lt;p&gt;
[runrig] was complaining about no mapcar in Perl so I wrote one in the chatterbox but it scrolled off.  So here are two better versions.&lt;p&gt;
mapcar is from lisp.  It is like [map] but works on more than one list.  While [map] loops setting $_ to successive elements of a list, mapcar loops setting @_ to successive elements of several lists (but since you can only pass one list to a subroutine, mapcar expects a list of references to one or more arrays).  Both [map] and mapcar collect the values returned by the code block or subroutine and then return the collected values.&lt;p&gt;
&lt;code&gt;
# Sample usage:
    my @array= ( [ 'a'..'c',undef ], [ 1..7 ], [ 'A'..'E' ] );
    my @trans= mapcar { [@_] } @array;
#   @transpose is now ( ['a',1,'A'],['b',2,'B'],['c',3,'C'],
#                       [undef,4,'D'],[5,'E'],[6] )
    my @transpose= mapcaru { [@_] } @array;
#   @trans is now ( ['a',1,'A'],['b',2,'B'],['c',3,'C'],
#                   [undef,4,'D'],[undef,5,'E'],[undef,6,undef] )
&lt;/code&gt;
So mapcaru puts [undef]s into @_ when one of the lists is shorter than any of the others while mapcar just leaves values out of @_.  Both versions are provided since the output of either cannot be easily converted into the other.
&lt;p&gt;
If you find yourself wishing for a special Perl variable that tracks which element of a list you are currently iterating over (in [map] or [for]), then you might find that mapcar is useful to you.</field>
<field name="snippetcode">
&lt;code&gt;
#!/usr/bin/perl -w

package mapcar;
use strict;
require Exporter;
use vars qw( $VERSION @EXPORT @ISA );
BEGIN {
    $VERSION= 1.01;
    @EXPORT= qw( mapcar mapcaru );
    @ISA= qw( Exporter );
}

sub mapcaru (&amp;@)
{
    my $sub= shift;
    if(  ! @_  ) {
        require Carp;
        Carp::croak( "mapcaru: Nothing to map" );
    }
    my $max= 0;
    for my $av (  @_  ) {
        if(  ! UNIVERSAL::isa( $av, "ARRAY" )  ) {
            require Carp;
            Carp::croak( "mapcaru: Not an array reference (",
                ref($av) ? ref($av) : $av, ")" );
        }
        $max= @$av   if  $max &lt; @$av;
    }
    my @ret;
    for(  my $i= 0;  $i &lt; $max;  $i++  ) {
        push @ret, &amp;$sub( map { $_-&gt;[$i] } @_ );
    }
    return wantarray ? @ret : \@ret;
}

sub mapcar (&amp;@)
{
    my $sub= shift;
    if(  ! @_  ) {
        require Carp;
        Carp::croak( "mapcar: Nothing to map" );
    }
    my $max= 0;
    for my $av (  @_  ) {
        if(  ! UNIVERSAL::isa( $av, "ARRAY" )  ) {
            require Carp;
            Carp::croak( "mapcar: Not an array reference (",
                ref($av) ? ref($av) : $av, ")" );
        }
        $max= @$av   if  $max &lt; @$av;
    }
    my @ret;
    for(  my $i= 0;  $i &lt; $max;  $i++  ) {
        push @ret, &amp;$sub( map { $i &lt; @$_ ? $_-&gt;[$i] : () } @_ );
    }
    return wantarray ? @ret : \@ret;
}

1;
&lt;/code&gt;</field>
</data>
</node>
