tags:

views:

83

answers:

2

I have an array of HTML::Elements obtained from HTML::TreeBuilder and HTML::Element->find and I need to assign their as_text value to some other variables. I know I can really easily do

my ($var1, $var2) = ($arr[0]->as_text, $arr[1]->as_text);

but I was hoping I could use map instead just to make the code a bit more readable as there are at least 8 elements in the array. I'm really new to Perl so I'm not quite sure what to do.

Can anyone point me in the right direction?

+10  A: 

If you're well versed in perldoc -f map it's pretty clear:

my @as_texts = map { $_->as_text } @arr;

Works as well if you want to assign to a list of scalars:

my($var1, $var2, $var3, ...) = map { $_->as_text } @arr;

But of course the array version is better for an unknown number of elements.

Chris Lutz
This is a major issue of personal preference but I prefer to use the EXPR form of `map` when the transform is simple enough: `map $_->as_text, @arr`.
hobbs
@hobbs - I often do to, but I wasn't sure if $_->as_text would work as expected in that case. I know `map chr, @arr` works, but I didn't know if method calls could be made to work the same way. I suppose the only way to find out is to test it, but in this specific case I personally prefer to use brackets.
Chris Lutz
@hobbs `map EXPR,LIST` is also faster than `map BLOCK LIST` but I am a sucker for the latter.
Sinan Ünür
@Chris: most stuff works, as long as you keep track of the arity of the functions you're calling and use parens for the "listop" ones. But it's always good to have a "when in doubt" rule. :)
hobbs
+1  A: 

Note that, if you just want to map the first two elements of @arr:

my($var1, $var2) = map { $_->as_text } @arr;

will invoke $_->as_text for all elements of @arr. In that case, use an array slice to avoid unnecessary calls:

my($var1, $var2) = map { $_->as_text } @arr[0 .. 1];

Example:

#!/usr/bin/perl

use strict;
use warnings;

my @arr = 'a' .. 'z';
my $count;
my ($x, $y) = map { $count++; ord } @arr;

print "$x\t$y\t$count\n";

$count = 0;
($x, $y) = map { $count++; uc } @arr[0 .. 1];

print "$x\t$y\t$count\n";

Output:

C:\Temp> jk
97      98      26
A       B       2

ord was called for each element of @arr whereas uc was called for only the elements we were interested in.

Sinan Ünür