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 points 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); closure_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% --