sub iter_hanoi { my ($disks, $start, $end, $via) = @_; return sub{} if $disks == 0; # Base case is empty, replace with empty sub # List of iterators, wrapped in sub{}s to delay their evaluation: my @sub_iter = ( sub { iter_hanoi($disks-1, $start, $via, $end) }, # Explicit return is assigned to array for iterator to shift sub { my @middle_val = ([$start, $end]); sub {shift @middle_val} }, sub { iter_hanoi($disks-1, $via, $end, $start) }, ); # Below here is boilerplate: if you've done the above steps right, just plug # this in, and it works. It returns the first iterator from the list that # returns anything. # Grab and unwrap an iterator from the list my $iter = (shift @sub_iter)->(); return sub { my $rval; $iter = (shift @sub_iter)->() until ($rval = $iter->() or @sub_iter == 0); return $rval; } }