[ABE.pm] mapping with an enclosure

Ricardo SIGNES perl.abe at rjbs.manxome.org
Fri Apr 4 13:43:11 PDT 2008


* "Faber J. Fedor" <faber at linuxnj.com> [2008-04-04T02:39:26]
> I'm reading in a CSV file line by line.  I need to trim leading and
> trailing whitespace out of each comma-delimited field. So I figured I'd
> use map an enclosure like so:

The following code contains no closures:

>     my @data = split(/,/, $_);
> 
>     map  {     $_ =>  s/^\s+//;
>                $_ =>  s/\s+$//;
>           } @data;
> 
>     ($sku,$warehouse,$quantity,$row,$product_type,$stack_location,$price)
>     = @data ;

You should use Text::CSV_XS.

> Two things I don't understand: 
> 
> 1) why is map editing my array in place?  It's supposed to return an
> array.  The array it does return has extra empty data elements in
> between each original element.

When you map, $_ is made an alias to the original value for each value in the
given list.  Altering $_ will alter the list.  To avoid that, you need to copy
the variable.

How do you know ANYTHING about the alias it returns?  You're not assigning the
result of map to anything.

> 2.  Why do I get a "Useless use of a variable in void context at
> at_test.pl line 19." (line 19 being the line map is on)?  

You probably thought you wanted to write:

  my @new_data = map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; } @data

That would be wrong.  Even if not, you used => instead of =~, so it complained
because that doesn't do anything meaningful.

You meant, maybe:

  my @new_data = map { my $str = $_; $str =~ s/^\s+//; $str =~ s/\s+//; $str }
                 @data;

If you don't need to leave @data intact as originally read:

  s/^\s+//, s/\s+$// for @data;

or

  s/(?:^\s+|\s+$)// for @data;

-- 
rjbs


More information about the ABE-pm mailing list