Lazy lists are good

Stackoverflow poster says Im looking for (how to make?) a function (module?) that gives nonzero integers between 1 and $input. Of course, in Perl, one can use the range operator to create such lists on the fly, as in 1 .. $input and most answers are along those lines.

perldoc perlop says:

In the current implementation, no temporary array is created when the range operator is used as the expression in “foreach” loops, but older versions of Perl might burn a lot of memory when you write something like this:

        for (1 .. 1_000_000) {
            # code
        }

Well, that’s excellent, but if you write my @x = (1 .. 1_000_000_000) or my $x = [1 .. 1_000_000_000], you’re going to have problems.

So, I thought I would suggest lazily generating the sequence (parameter checking etc omitted):

sub make_lazy_increasing_sequence {
    my ($current, $end) = map int, @_;
    return sub {
        return if $current > $end;
        return $current++;
    }
}

This returns an anonymous function which closes over the private instances of $current and $end. The line:

my $counter = make_lazy_increasing_sequence(1, 10);

creates a function that will generate integers between 1 and 10.

The line:

my $huge_counter = make_lazy_increasing_sequence(1, 10_000_000_000);

generates one that will yield a much longer sequence.

You can’t generate open ended sequences using the range operator. On the other hand, it is trivial to do so using closures:

my $neverending_increasing_sequence_from_5 = sub {
    my ($x) = @_;
    return sub { $x++ };
 }->(5);
say $neverending_increasing_sequence_from_5->() for 1 .. 10;