#!/usr/bin/perl
# Idiom #319 generator functions
use feature 'say';
use strict;
# predeclare _upto with prototype (&) so it expects an anonymous sub
# without this, the iterator won't work inside a foreach loop (only while)
# see https://p...content-available-to-author-only...l.org/perlsub#Prototypes
sub _upto
(&) { return $_[0]; }
# define a closure over $start and $end
# see https://p...content-available-to-author-only...l.org/perlfaq7#What%27s-a-closure?
sub upto {
my ($start, $end) = @_;
my $n = $start;
# in an array context, return list $start..$end
# in scalar context"
# if we've reached the end, reset $n to $start and return an empty list
# (which in scalar context will be taken as false and stop the loop)
# otherwise increment $n and return it
$n > $end ? ($n = $start, ()) :
$n++
;
};
}
my $it = upto(3, 5);
foreach ( $it->() ) { print ' ' . $_ }
$it = upto(2, 6);
while ( my $n = $it->() ) { print ' ' . $n }
# In array context, upto can be used to generate a range.
# For that it uses perl's .. operator to generate an actual
# list of numbers, So this use case isn't an example of an
# iterator. The functionality is provided in upto just so it
# would be a bit more generally useful.
my $range = upto(7, 11);
my @list = $range->();
IyEvdXNyL2Jpbi9wZXJsCgojIElkaW9tICMzMTkgZ2VuZXJhdG9yIGZ1bmN0aW9ucwoKdXNlIGZlYXR1cmUgJ3NheSc7CnVzZSBzdHJpY3Q7CgojIHByZWRlY2xhcmUgX3VwdG8gd2l0aCBwcm90b3R5cGUgKCYpIHNvIGl0IGV4cGVjdHMgYW4gYW5vbnltb3VzIHN1YgojIHdpdGhvdXQgdGhpcywgdGhlIGl0ZXJhdG9yIHdvbid0IHdvcmsgaW5zaWRlIGEgZm9yZWFjaCBsb29wIChvbmx5IHdoaWxlKQojIHNlZSBodHRwczovL3AuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmwub3JnL3BlcmxzdWIjUHJvdG90eXBlcwpzdWIgX3VwdG8gKCYpIHsgcmV0dXJuICRfWzBdOyB9ICAKCiMgZGVmaW5lIGEgY2xvc3VyZSBvdmVyICRzdGFydCBhbmQgJGVuZAojIHNlZSBodHRwczovL3AuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmwub3JnL3BlcmxmYXE3I1doYXQlMjdzLWEtY2xvc3VyZT8Kc3ViIHVwdG8gewogICAgbXkgKCRzdGFydCwgJGVuZCkgPSBAXzsKCiAgICBteSAkbiA9ICRzdGFydDsKCiAgICByZXR1cm4gX3VwdG8gewogICAgICAgIHJldHVybgogICAgICAgICAgICAjIGluIGFuIGFycmF5IGNvbnRleHQsIHJldHVybiBsaXN0ICRzdGFydC4uJGVuZAogICAgICAgICAgICAjIGluIHNjYWxhciBjb250ZXh0IgogICAgICAgICAgICAjICAgaWYgd2UndmUgcmVhY2hlZCB0aGUgZW5kLCByZXNldCAkbiB0byAkc3RhcnQgYW5kIHJldHVybiBhbiBlbXB0eSBsaXN0CiAgICAgICAgICAgICMgICAod2hpY2ggaW4gc2NhbGFyIGNvbnRleHQgd2lsbCBiZSB0YWtlbiBhcyBmYWxzZSBhbmQgc3RvcCB0aGUgbG9vcCkKICAgICAgICAgICAgIyAgIG90aGVyd2lzZSBpbmNyZW1lbnQgJG4gYW5kIHJldHVybiBpdAogICAgICAgICAgICB3YW50YXJyYXkgPyAkc3RhcnQgLi4gJGVuZCAgICA6CiAgICAgICAgICAgICRuID4gJGVuZCA/ICgkbiA9ICRzdGFydCwgKCkpIDoKICAgICAgICAgICAgJG4rKwogICAgICAgICAgICA7CiAgICAgICAgfTsKfQoKbXkgJGl0ID0gdXB0bygzLCA1KTsKCnByaW50ICdmb3JlYWNoOic7CmZvcmVhY2ggKCAkaXQtPigpICkgeyBwcmludCAnICcgLiAkXyB9CnByaW50ICJcbiI7CgokaXQgPSB1cHRvKDIsIDYpOwoKcHJpbnQgJ3doaWxlOiAgJzsKd2hpbGUgKCBteSAkbiA9ICRpdC0+KCkgKSB7IHByaW50ICcgJyAuICRuIH0KcHJpbnQgIlxuIjsKCiMgSW4gYXJyYXkgY29udGV4dCwgdXB0byBjYW4gYmUgdXNlZCB0byBnZW5lcmF0ZSBhIHJhbmdlLgojIEZvciB0aGF0IGl0IHVzZXMgcGVybCdzIC4uIG9wZXJhdG9yIHRvIGdlbmVyYXRlIGFuIGFjdHVhbAojIGxpc3Qgb2YgbnVtYmVycywgIFNvIHRoaXMgdXNlIGNhc2UgaXNuJ3QgYW4gZXhhbXBsZSBvZiBhbiAKIyBpdGVyYXRvci4gIFRoZSBmdW5jdGlvbmFsaXR5IGlzIHByb3ZpZGVkIGluIHVwdG8ganVzdCBzbyBpdAojIHdvdWxkIGJlIGEgYml0IG1vcmUgZ2VuZXJhbGx5IHVzZWZ1bC4KbXkgJHJhbmdlID0gdXB0byg3LCAxMSk7CnByaW50ICdsaXN0IGNvbnRleHQ6ICc7Cm15IEBsaXN0ID0gJHJhbmdlLT4oKTsKcHJpbnQgam9pbiAnICcsIEBsaXN0OwpwcmludCAiXG4iOwo=