Skip to content
An experiment to use perl syntax and built-ins with iterators/generators
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.



Tie::Iterator - Work with an iterator like an array


version 0.001


tie my @iter, 'Tie::Iterator', sub { };
for my $item ( @iter ) {



This is an attempt to add a more-transparent iterator to Perl. The full solution must work transparently in all useful list-type things:

for my $item ( @iter )
map { ... } @iter
grep { ... } @iter
sort { ... } @iter


Why A Core Iterator?

  • while ( defined( my $i = $iter->() ) )

    The current iterator pattern is unintuitive and requires a set of iterator-specific functions to implement map, grep, and sort.

    Iterator::Simple is the best way of doing iterators available on CPAN, but it requires a CPAN module and so can only do what CPAN modules can do. This isn't itself a reason for adding a core iterator, but it should be considered.

  • A Better for ( <$fh> ) Pattern

    New users often try to do a `for` loop over a filehandle and get confused when it fails or performs poorly on very large files. Another pattern that must be learned: while ( my $line = <$fh )>.

    An "iterable" filehandle would allow while and for to be treated equally.

  • Cannot be implemented on CPAN.

    This module is an attempt to use tie to make an array that had an iterator underneath. It fails because tied arrays cannot be returned from subs, since only lists are allowed to be returned from subs.

    It would work with an arrayref, but this is not transparent, and as soon as the array being referenced is given to map, grep, for, sort, or otherwise, the array is reduced to a list, which will run the iterator until exhaustion.

    Solving that problem doesn't make everything work, because an array must know exactly how big they are before map or grep will work on them. See t/iterator.t 'map iterator' for a failing test for this. Since for allows modification of the array during iteration, tied arrays work just fine.

Possible Syntax

  • Magic "iterable" flag on @array

    If the magic flag is there, @array is really either a sub or a filehandle.

    This is both the most magic and the least amount of user work.

    • use feature qw( iterator ); my @iter = iterator { };

      @array is now backed by an iterator.

      gather is not used as the function name because we are not implementing take.

    • use feature qw( iterator ); my @iter = iterator $fh;

      If the iterator gets a GLOB or IO::Handle, it does the right thing.

      In fact, most of Iterator::Simple's functionality could work this way.

    • open my @fh, '<', 'FILENAME'

      @fh is now an iterable filehandle according to $/ at the time of reading the next line.

      This is currently allowed (is not a syntax error), and under no strict "refs" creates a filehandle called "0".

  • <@array>

    This is already used as a glob() operation, so this would be a backwards- incompatible change. Evil.

  • @&array or &@array

    The first one is a syntax error currently. The second can sometimes be interpreted as bitwise-& @array.


  • XS code that works with arrays may need to handle iterables differently, especially with the magic version.

    This would break the abstraction quite impressively, and a leaky abstraction is frequently worse than no abstraction at all...


Doug Bell


This software is copyright (c) 2014 by Doug Bell.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


Hey! The above document had some coding errors, which are explained below:

  • Around line 70:

    '=item' outside of any '=over'

You can’t perform that action at this time.