in reply to An efficient way to do this?

You could use a closure something like this:

$ perl -le' use Socket; sub IP_iter { my ( $start, $end ) = map unpack( "N", inet_aton $_ ), @_; my $count; sub { $count = shift; $count = $count > $end - $start ? $end - $start + 1 : $count; return map inet_ntoa( inet_aton $start++ ), 1 .. $count; } } my $ip = IP_iter "1.1.1.1", "1.1.1.12"; print for $ip->( 5 ); print ""; print for $ip->( 5 ); ' 1.1.1.1 1.1.1.2 1.1.1.3 1.1.1.4 1.1.1.5 1.1.1.6 1.1.1.7 1.1.1.8 1.1.1.9 1.1.1.10

Replies are listed 'Best First'.
Re^2: An efficient way to do this?
by locked_user sundialsvc4 (Abbot) on Feb 06, 2008 at 15:49 UTC

    Whether or not you use a closure, it's probably a good idea to “turn your thinking inside-out” on this one. (And a closure, if you grok that, might be a very good way to do that.)

    Instead of putting four nested loops into the driver's seat and figuring out how to push the “pause” button after you have accumulated 50 results, put a loop (1..50) into the driver's seat.

    Each time through the loop, you call a function which, given an internal state (a vector of 4 values corresponding to the nested-loops you are now using), returns a value and the updated state. (Or it retains that state within the closure.)

    So your subroutine, conceptually, looks rather like this fragment...

    &initialize_state(\@state_vector); for my $i (1..50) { my $value = &get_next_value(\@state_vector); &process_value($i, $value); &advance_state(\@state_vector); }

    Footnote:   a “closure” is a pointer to “an instance of a subroutine.” Once you do this, the closure “has a life of its own” and each instance of the closure stands-apart from all the other instances. It's wicked-cool when you need it, but it can create strange blank looks on the faces of your colleagues... who might well decide, “well, Joe wrote this, and Joe understands it, so let's let Joe fix it ... forever...” In other words, you might have created your own wicked-cool pain in your butt. :=)