Subject: | Use a blessed arrayref for Var::Pairs::Pair instead of an inside-out object |
The attached script (bench.pl) takes 17 seconds to run (on my netbook) using the current CPAN release of Var::Pairs. Patching it to use a blessed array reduces the run time to 9 seconds.
Pros:
- Speed.
- Allows my($k,$v)=@$pair to "just work". This seems a natural idiom.
- Data::Dumper-friendly output.
- Possible future speed improvements using Class::XSAccessor::Array.(Current version seems slightly buggy for lvalues.)
Cons:
- General encapsulation concerns regarding non-inside-out objects apply.
- More specifically, people might think that assigning to $pair->[0] or $pair->[1] or even @$pair will do something useful. (It won't; it will just break the object subtly.)
Subject: | bench.pl |
use Var::Pairs qw(each_pair);
my @vals = 1..500;
for my $v (@vals)
{
while (my $pair = each_pair @vals)
{
my $x = $pair->index + $pair->value;
$pair->value = $x;
}
}
Subject: | var-pairs-pair-blessed-arrayref.diff |
diff -urN Var-Pairs-0.001005/lib/Var/Pairs.pm Var-Pairs-0.001005-mine/lib/Var/Pairs.pm
--- Var-Pairs-0.001005/lib/Var/Pairs.pm 2014-03-11 10:17:52.000000000 +0000
+++ Var-Pairs-0.001005-mine/lib/Var/Pairs.pm 2014-04-05 13:51:06.139957217 +0100
@@ -279,32 +279,26 @@
# Class implementing each key/value pair...
package Var::Pairs::Pair {
- use Hash::Util qw< fieldhash >;
use Scalar::Util qw< looks_like_number >;
use Data::Alias;
use Carp;
- # Each pair object has two attributes...
- fieldhash my %key_for;
- fieldhash my %value_for;
-
# Accessors for the attributes (value is read/write)...
- sub value :lvalue { $value_for{shift()} }
- sub index { $key_for{shift()} }
- sub key { $key_for{shift()} }
+ sub value :lvalue { shift->[1] }
+ sub index { shift->[0] }
+ sub key { shift->[0] }
- # The usual inside-out constructor...
sub new {
my ($class, $key, $container_ref, $container_type) = @_;
- # Create a scalar based object...
- my $new_obj = bless \do{ my $scalar }, $class;
+ # Create an array based object...
+ my $new_obj = bless [], $class;
# Initialize its attributes (value needs to be an alias to the original)...
- $key_for{$new_obj} = $key;
- alias $value_for{$new_obj} = $container_type eq 'array' ? $container_ref->[$key]
- : $container_type eq 'none' ? $_[2]
- : $container_ref->{$key};
+ $new_obj->[0] = $key;
+ alias $new_obj->[1] = $container_type eq 'array' ? $container_ref->[$key]
+ : $container_type eq 'none' ? $_[2]
+ : $container_ref->{$key};
return $new_obj;
}
@@ -314,18 +308,18 @@
# As a string, a pair is just: key => value
q{""} => sub {
my $self = shift;
- my $value = $value_for{$self};
+ my $value = $self->[1];
$value = ref $value ? ref $value
: looks_like_number($value) ? $value
: qq{"$value"};
- return "$key_for{$self} => $value";
+ return "$self->[0] => $value";
},
# Can't numerify a pair (make it a hanging offence)...
q{0+} => sub { croak "Can't convert Pair(".shift.") to a number" },
# All pairs are true (just as in Perl 6)...
- q{bool} => sub { 1 },
+ q{bool} => sub { !!1 },
# Everything else as normal...
fallback => 1,