use strict;
use Data::Dumper;
sub for_pairs (&@) {
unless (@_&1) {
warn "Odd";
push @_, undef;
goto \&for_pairs;
}
my $code = shift;
# Localise $a and $b
# (borrowed from List-MoreUtils)
my ($caller_a, $caller_b) = do {
my $pkg = caller();
no strict 'refs';
\*{$pkg.'::a'}, \*{$pkg.'::b'};
};
local(*$caller_a, *$caller_b);
no warnings;
if (wantarray) {
# list context
map {(*$caller_a, *$caller_b) = \splice(@_, 0, 2); $code->()}
+(1..@_/2)
}
elsif (defined wantarray) {
# scalar context
# count number of returned elements
my $i=0;
# force list context with =()= for the count
$i +=()= $code->() while (*$caller_a, *$caller_b) = \splice(@_
+, 0, 2);
$i
}
else {
# void context
$code->() while (*$caller_a, *$caller_b) = \splice(@_, 0, 2);
}
}
#---------------------------------------------
my $Incoming = 'uno="one" Blah blah dos="two" * More Noise* tres="thr
+ee"';
my %att= (PREEXISTING=>"val1", ANOTHER=>"Val2");
for_pairs { $att{$a} = $b } $Incoming=~m/\b(\w+)="(.+?)"/g;
print Dumper \%att;
I don't think I will use it in my current app - I'll stick with the one-liner above.
For future apps with access to Modules, It would be better to go with an established module that provides the function.
Anyway - This has been a fun exercise. Thank you.
Syntactic sugar causes cancer of the semicolon. --Alan Perlis
|