Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
I read somewhere that said something like:
     Object is data wrapped in methods.
     Closure is subroutine wrapped in data.
Instead of talking about the philosophical differences first, I ran some benchmarks to compare closure and object, just for the fun of it. I have the following three results:

Counter:
use strict; use warnings; use Benchmark qw(cmpthese); # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - sub closure_counter { my $count = shift; return sub { $count++ }; } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {package obj_counter; sub new {bless {count=>$_[1]};} sub count {return ($_[0]->{count})++} } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - my $obj_counter = obj_counter->new(3); my $closure_counter = closure_counter(3); cmpthese(1000, { obj_counter=>sub{$obj_counter->count()for 1..1000;}, closure_counter=>sub{$closure_counter->()for 1..1000;} } ); __END__ Benchmark: timing 1000 iterations of closure_counter, obj_counter... closure_counter: 2 wallclock secs ( 2.58 usr + 0.00 sys = 2.58 CPU) + @ 387.60/s (n=1000) obj_counter: 5 wallclock secs ( 5.22 usr + 0.00 sys = 5.22 CPU) @ 1 +91.57/s (n=1000) Rate obj_counter closure_counter obj_counter 192/s -- -51% closure_counter 388/s 102% --

Directory Iterator:
use strict; use warnings; use Benchmark qw(cmpthese); # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - use IO::Dir; sub closure_dir_iter { my $dir = IO::Dir->new(shift); return sub { my $fl = $dir->read(); $dir->rewind() unless defined $fl; return $fl; }; } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {package obj_dir_iter; use IO::Dir; sub new {bless {dir=>IO::Dir->new($_[1])};} sub iter { my $fl = $_[0]->{dir}->read(); $_[0]->{dir}->rewind() unless defined $fl; return $fl; } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - my $obj_dir_iter = obj_dir_iter->new( "." ); my $closure_dir_iter = closure_dir_iter( "." ); cmpthese(500, { obj_dir_iter=>sub{while(defined(my $f = $obj_dir_iter->iter()) +){print "$f\n";}}, closure_dir_iter=>sub{while(defined(my $f = $closure_dir_iter- +>())){print "$f\n";}} } ); __END__ Benchmark: timing 2000 iterations of closure_dir_iter, obj_dir_iter... obj_dir_iter: 1 wallclock secs ( 1.20 usr + 0.00 sys = 1.20 CPU) @ +1666.67/s (n=2000) closure_dir_iter: 1 wallclock secs ( 1.10 usr + 0.00 sys = 1.10 CPU +) @ 1818.18/s (n=2000) Rate obj_dir_iter closure_dir_iter obj_dir_iter 1667/s -- -8% closure_dir_iter 1818/s 9% --

Turtle Graph (drawing Koch curve):
use strict; use warnings; use Benchmark qw(cmpthese); # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - use constant PI => 3.14159265359; sub closure_turtle { my ($h, $xy) = (0, [[0],[0]]); # h = heading (0 - north, 90 - +east, etc) return sub { $h = $h + (shift || 0); # accumulative turns in degree my $d = shift || 0; # distance $xy->[0][scalar(@{$xy->[0]})] = $d*sin(PI*$h/180) + $xy->[0][$ +#{@{$xy->[0]}}]; $xy->[1][scalar(@{$xy->[1]})] = $d*cos(PI*$h/180) + $xy->[1][$ +#{@{$xy->[1]}}]; return $xy; }; } sub closure_koch { my ($turtle, $d, $level) = @_ ; if ($level==0) {$turtle->(0,$d); return 1;} $turtle->( 0,0); closure_koch($turtle,$d/3,$level-1); $turtle->(-60,0); closure_koch($turtle,$d/3,$level-1); $turtle->(120,0); closure_koch($turtle,$d/3,$level-1); $turtle->(-60,0); closure_koch($turtle,$d/3,$level-1); } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {package obj_turtle; use constant PI => 3.14159265359; sub new {return bless({h=>0,xy=>[[0],[0]]});} sub rt {$_[0]->{h}=$_[0]->{h}+$_[1];} # right turn by x + degrees sub fd { # forward by x poi +nts my ($h, $xy, $d) = ($_[0]->{h}, $_[0]->{xy}, $_[1]); $xy->[0][scalar(@{$xy->[0]})] = $d*sin(PI*$h/180) + $xy->[0][$ +#{@{$xy->[0]}}]; $xy->[1][scalar(@{$xy->[1]})] = $d*cos(PI*$h/180) + $xy->[1][$ +#{@{$xy->[1]}}]; $_[0]->{xy} = $xy; return $xy; } } sub obj_koch { my ($turtle, $d, $level) = @_ ; if ($level==0) {$turtle->fd($d); return 1;} $turtle->rt( 0); obj_koch($turtle, $d/3,$level-1); $turtle->rt(-60); obj_koch($turtle, $d/3,$level-1); $turtle->rt(120); obj_koch($turtle, $d/3,$level-1); $turtle->rt(-60); obj_koch($turtle, $d/3,$level-1); } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - my $obj_turtle = obj_turtle->new(); my $closure_turtle = closure_turtle(); cmpthese(100, { obj_turtle=>sub{for(0..2){$obj_turtle->rt(120); obj_koch($obj_ +turtle,170,4);}}, closure_turtle=>sub{for(0..2){$closure_turtle->(120, 0); closu +re_koch($closure_turtle,170,4);}} } ); __END__ Benchmark: timing 100 iterations of closure_turtle, obj_turtle... closure_turtle: 6 wallclock secs ( 6.49 usr + 0.00 sys = 6.49 CPU) +@ 15.41/s (n=100) obj_turtle: 5 wallclock secs ( 4.99 usr + 0.00 sys = 4.99 CPU) @ 20 +.04/s (n=100) Rate closure_turtle obj_turtle closure_turtle 15.4/s -- -23% obj_turtle 20.0/s 30% --


Closure counter beat object's by ~100%; Closure directory iterator beat object's by ~10%; but object turtle beat closure's by ~30%.

Why the difference?

Going from empirical to completely academic and philosophical, closure has pretty good application in lambda calculus. Consider the following code (we use "%" place of "lambda"):
# IF = %b.(%x.(%y.(b x) y)) $IF = sub { my $b = shift; sub { my $x = shift; sub { my $y = shift; $b->($x)->($y); } } } # TRUE = %x.(%y.x) $TRUE = sub { my $x = shift; sub { my $y = shift; $x; } } # FALSE = %x.(%y.y) $FALSE = sub { my $x = shift; sub { my $y = shift; $y; } } print $IF->($TRUE)->("then")->("else"); # prints "then" print $IF->($FALSE)->("then")->("else"); # prints "else"
To verify algebraically
        (IF TRUE A B)
observe that
        (%b.%x.%y.(b x y) %a.%b.a A B)
           (%x.%y.(%a.%b.a x y)   A B)
              (%y.(%a.%b.a A y)     B)
                  (%a.%b.a A B)
                     (%b.A   B)
                         A
Likewise, (IF FALSE A B) gives us B. (Full discussion can be found here.)

Is it a big deal? Well, set theory and mathematical logic may look naively useless (which after all only give us Incompleteness Theorem); or number theory or group/fields theory may seem trivial (where only comes some obscure Elliptic Curves for us to make highly unbreakable encryption).

Lisp, considered a functional language, where closure's considered a major technique, is often used to implement A.I. stuff--somewhere along the line, there come RegEx, Mathematica, and taken-for-granted stuff like that.

Is closure (and functional programming) for everyone? Not when a third of the bookshelves in Computer section in the major bookstores are stuffed with Java and OOP. It's hard to be Func-ie when almost everyone else is Ob-ing.

But then, if somebody could find good use of group theory, somebody could surely find meaningful application of closure and functional programming. It's just a matter of creativity and practice.

In reply to Re: (On Speed Diff, etc.) Closure on Closures (beta) by chunlou
in thread Closure on Closures by broquaint

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others romping around the Monastery: (5)
    As of 2014-09-22 05:47 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      How do you remember the number of days in each month?











      Results (180 votes), past polls