use strict; use warnings; sub reduce(&@) { my $f = shift; my $a = shift; if (prototype($f)||'' eq '$$') { $a = $f->($a, shift) while @_; } else { my $b; no strict 'refs'; my $caller = caller(); local *{$caller."::a"} = \$a; local *{$caller."::b"} = \$b; $b = shift, $a = $f->() while @_; } return $a; } sub prototyped($$) { $_[0] * $_[1] } sub unprototyped { $a * $b } $\ = "\n"; print reduce { $a * $b } 1..6; # 720 print reduce \&prototyped, 1..6; # 720 print reduce \&unprototyped, 1..6; # 720