use Benchmark qw/cmpthese/;
use List::Util qw/reduce/;
sub kvmap (&@) {
my ( $f, @kv ) = @_;
my $key = 0;
local ( $a, $b );
return map {
( $key ^= 1 ) ? do { $a = $_; () } : do { $b = $_; $f->($a, $b) }
} @kv;
}
my @data = my %data = (
action => 'submit',
type => 'comment',
message => 'Hello'
);
cmpthese -5, {
ex1 => sub {
my @output;
while ( my ($k,$v) = splice(@data,0,2) ) {
push @output, "$k=$v"
}
join( "&", @output );
},
ex2 => sub {
my @output;
my @copy = @data;
while ( my ($k,$v) = splice(@copy,0,2) ) {
push @output, "$k=$v"
}
join( "&", @output );
},
ex3 => sub {
my @output;
while ( my ($k,$v) = each %data ) {
push @output, "$k=$v"
}
join( "&", @output );
},
ex4 => sub {
join "&", map { "$_->[0]=$_->[1]" } map { @$_ } reduce {
! @$a || ref $a->[-1] ? push @$a, $b : push @$a, [pop @$a, $b]; $a
} [], @data;
},
ex5 => sub {
join "&", map { @{$_->[0]} } reduce {
ref $a->[-1] ? push @$a, $b : push @{$a->[0]}, pop(@$a) . "=$b"; $a
} [[]], @data;
},
inline_kvmap => sub {
my $key = 0;
local ( $a, $b );
join '&', map {
( $key ^= 1 ) ? do { $a = $_; () } : do { "$a=$_" }
} @data;
},
call_kvmap => sub {
join '&', kvmap { "$a=$b" } @data;
}
};
####
sub TIESCALAR { bless \my $o => $_[0] }
sub STORE { $_[1] = "Touched by STORE\n" }
tie my $a => 'main';
my $b = "Untouched by STORE\n";
$a = $b;
print $b; # => Untouched by STORE
tied($a)->STORE($b);
print $b; # => Touched by STORE
##
##
sub walk {
my ( $ref ) = @_;
return "$ref" if blessed $ref;
given ( ref $ref ) {
when ( '' ) { return $ref; }
when ( 'ARRAY' ) { return map { walk($_) } @$ref; }
when ( 'HASH' ) { return map { $_ => walk($ref->{$_}) } keys %$ref; }
default { carp "I'm confused by $ref" }
}
}
##
##
{
my ( $test, $modify );
sub walk {
my $ref;
( $test, $modify, $ref ) = @_;
ref $modify eq 'CODE' and ref $test eq 'CODE' or croak 'First 2 arguments must be coderefs';
return _walk($ref);
}
sub _walk {
my ( $ref ) = @_;
return $modify->($ref) if $test->($ref);
given ( ref $ref ) {
when ( '' ) { return $ref; }
when ( 'ARRAY' ) { return map { _walk($_) } @$ref; }
when ( 'HASH' ) { return map { $_ => _walk($ref->{$_}) } keys %$ref; }
default { carp "I'm confused by $ref" }
}
}
}
##
##
my ( $gold ) = $data =~ /$rx/
##
##
qr/(foo).*(foo)(?{ $_ =~ s+foo+bar+g })/
##
##
use re 'eval';
my $rx = qr/$rx_with_foo(?{ $_ =~ s+foo+bar+g })/
##
##
{
package A;
use fields qw/a/;
sub new {
return fields::new(shift);
}
sub legal_keys {
my ( $self ) = @_;
print $self, "\n";
return Hash::Util::legal_keys $self;
}
}
my $a = A->new;
print $a->legal_keys, "\n";
print $a, "\n";
print Hash::Util::legal_keys($a), "\n";