Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Re^2: May Thy Closures Be Blessed

by adrianh (Chancellor)
on Apr 26, 2004 at 15:34 UTC ( [id://348215]=note: print w/replies, xml ) Need Help??


in reply to Re: May Thy Closures Be Blessed
in thread May Thy Closures Be Blessed

An interesting discussion would be the differences between this and Inside-out classes. Both are based on lexical scoping to enforce encapsulation. What are the benefits/drawbacks of either method?

Off the top of my head:

  • You don't have to mess around with DESTROY with the closure based method, which makes maintenance easier.
  • Inside out objects are more space efficient than closures.
  • Accessing object state is a subroutine call with closure objects, and a hash access with inside-out objects. The latter will be a fair bit faster.
  • You can subclass an existing non-inside-out object and add inside-out based state to the objects in the subclass. You can't do this with without delegation with closures.
  • You need a bit more mechanism than the proposal hardburn showed above to get separate namespaces for state in different subclasses. This comes for free with inside-out.
  • You don't get compile-time checking of your instance variable naming with closures.
  • added 16:58 GMT+1:Inside out instance variables are scoped to the class they are declared in. With the mechanism outlined in the OP instance variables can also be accessed in subclasses.

Replies are listed 'Best First'.
Re: May Thy Closures Be Blessed
by Abigail-II (Bishop) on Apr 26, 2004 at 16:35 UTC
    Inside Out objects are faster than the closure based - but compared to "traditional" objects, the difference is small:
    #!/usr/bin/perl use strict; use warnings; use Benchmark qw /cmpthese/; use Carp; package Class_Closure; sub new { my $class = shift; my %args = @_; my %field = ( name => $args {name} || "abigail", colour => $args {colour} || "pink", age => $args {age} || 100, class => $class, ); bless sub { my $name = shift; my ($package, $filename, $line) = caller; die "Attempt to access private class data " . "for $field{class} at $filename line $line\n" unless UNIVERSAL::isa ($package => __PACKAGE__); die "No such field '$name' at $filename line $line\n" unless exists $field{$name}; die "You can't change the class name at $filename line $line\n +" if $name eq 'class'; $field {$name} = shift if @_; $field {$name} } => $class; } sub name {my $self = shift; $self -> (name => @_)} sub colour {my $self = shift; $self -> (colour => @_)} sub age {my $self = shift; $self -> (age => @_)} sub format { my $self = shift; join " " => $self -> ('name'), $self -> ('colour'), $self -> ('age +'); } package Class_Inside_Out; my %name; my %colour; my %age; sub new { my $key = bless \(my $dummy) => shift; my %args = @_; $name {$key} = $args {name} || "abigail"; $colour {$key} = $args {colour} || "pink"; $age {$key} = $args {age} || 100; $key; } sub name { my $key = shift; $name {$key} = shift if @_; $name {$key}; } sub colour { my $key = shift; $colour {$key} = shift if @_; $colour {$key}; } sub age { my $key = shift; $age {$key} = shift if @_; $age {$key}; } sub format { my $key = shift; join " " => $name {$key}, $colour {$key}, $age {$key}; } package Class_Traditional; sub new { my $class = shift; my %args = @_; bless {name => $args {name} || "abigail", colour => $args {colour} || "pink", age => $args {age} || 100} => $class; } sub name { my $self = shift; $self -> {name} = shift if @_; $self -> {name} } sub colour { my $self = shift; $self -> {colour} = shift if @_; $self -> {colour} } sub age { my $self = shift; $self -> {age} = shift if @_; $self -> {age} } sub format { my $self = shift; join " " => @$self {qw /name colour age/}; } package main; our $obj_c = Class_Closure -> new; our $obj_i = Class_Inside_Out -> new; our $obj_t = Class_Traditional -> new; our @names = ("Larry Wall", "Damian Conway", "Nicholas Clark", "Gurusamy Sarathy", "Chip Salzenberg", "Rafael Garcia-Suarez"); our @colours = qw /red green blue white yellow orange brown purple vio +let/; # # Test. # my $name = $names [rand @names]; my $colour = $colours [rand @colours]; my $age = 1 + int rand 100; foreach my $i ([obj_c => $obj_c], [obj_i => $obj_i], [obj_t => $obj_t] +) { $i -> [1] -> name ($name); $i -> [1] -> colour ($colour); $i -> [1] -> age ($age); die $i -> [0] unless "$name $colour $age" eq $i -> [1] -> format; } our $dummy; cmpthese -1 => { closure => 'foreach my $n (@names) { foreach my $c (@colours) { my $age = 1 + int rand 100; $obj_c -> name ($n); $obj_c -> colour ($c); $obj_c -> age ($age); $dummy = $obj_c -> format; } }', inside_out => 'foreach my $n (@names) { foreach my $c (@colours) { my $age = 1 + int rand 100; $obj_i -> name ($n); $obj_i -> colour ($c); $obj_i -> age ($age); $dummy = $obj_i -> format; } }', traditional => 'foreach my $n (@names) { foreach my $c (@colours) { my $age = 1 + int rand 100; $obj_t -> name ($n); $obj_t -> colour ($c); $obj_t -> age ($age); $dummy = $obj_t -> format; } }', }; __END__ Rate closure inside_out traditional closure 355/s -- -25% -75% inside_out 473/s 33% -- -67% traditional 1436/s 304% 203% --

    Abigail

      This is probably due to inefficient stringification of the object reference. Maybe the stringified value should be put into the PV portion and POK should be set on while doing Perl_sv_2pv_flags ?
        This is probably due to inefficient stringification of the object reference. Maybe the stringified value should be put into the PV portion and POK should be set on while doing Perl_sv_2pv_flags ?

        I think this evaluation is spot on. If you change the inside-out implementation to something that avoids stringification:

        You get something much more reasonable:

        Rate closure inside_out traditional closure 177/s -- -43% -45% inside_out 313/s 76% -- -3% traditional 321/s 81% 3% --

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://348215]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-04-16 22:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found