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% --