John Millaway


Tie::Scalar::RingBuffer - Treat a scalar as a ring buffer iterator.


  use Tie::Scalar::RingBuffer;

  tie $in_order,    'Tie::Scalar::RingBuffer', \@data;
  tie $every_other, 'Tie::Scalar::RingBuffer', \@data, { increment => 2 };
  tie $backwards,   'Tie::Scalar::RingBuffer', \@data, { start_offset => $#data, increment => -1 };
  tie $random,      'Tie::Scalar::RingBuffer', \@data, { random => 1 };

  # Alternate CSS row shading for HTML table rows:
  @css_shades  =  qw(normal_row shaded_row);
  tie $row_shade, 'Tie::Scalar::RingBuffer', \@css_shades;

  foreach (@html_rows) {
      print qq( <tr class="$row_shade"> );
      print qq( <td> $_ </td> ) foreach (@$_);
      print qq( </tr> );


This module ties a $scalar to a @list so that every time you access the $scalar, you are really accessing the next element in the list. The list is treated as a ring buffer, so there is no 'end' to the iteration.


A ring buffer is a queue in which the tail and head are logically connected so that there is effectively no end to the queue. This modules treats a listref as a ring buffer, and creates an iterator for that ring buffer. The iteration is completely hidden; there is no need to call next() method, nor is there an at_end() method. Every time you access the iterator, you get the next value from the list. The iterator wraps around at the end of the list (or at the beginning if you are iterating backwards), and will iterate forever.


tie SCALAR, Tie::Scalar::RingBuffer, LISTREF [, OPTIONS]

Ties SCALAR to LISTREF. Each time SCALAR is accessed, it produces the next element in LISTREF. You can control how the next element is found by specifying "OPTIONS". Currently, there is no need to call untie().


    my @dilemma = qw(she loves me. she loves me not.);
    tie $answer, 'Tie::Scalar::RingBuffer', \@dilemma;
    while (1){
        print "$answer "

which prints, "she loves me. she loves me not. she loves " ... and so on.

The OPTIONS hashref, if present, may contain the following key-value pairs:

start_offset => NUM

Specifies the the starting point in the list. start_offset is only used when you tie the list, and is not used afterwards.

default: 0.

increment => NUM

At each access, NUM is added to the current index to produce the new index. To iterate backwards, specify increment => -1. If increment is 0, you get the same element every time.

default: 1.

random => BOOLEAN

If BOOLEAN is true, then you get a random element from the list every time.

default: 0.


The redo method produces the same result as the previous FETCH did. If $scalar is tied, then,

    $x = $scalar;
    $y = tied($scalar)->redo();

leaves $x == $y.


Assignment (STORE) is performed on the same index that was used for previous FETCH. The following is a pathetic attempt to escape one's destiny:

    my @dilemma = qw(she loves me. she loves me not.);
    tie $answer, 'Tie::Scalar::RingBuffer', \@dilemma;
    for (0..$#dilemma){
        $answer = 'so.' if $answer =~ m/not/;
        print tied($answer)->redo(), " ";

The above code has the same effect as:

    $dilemma[6] = 'so.';


See Tie::Array::Iterable for a more complex, C++-style iterator.


John Millaway <>


Copyright 2003 by John Millaway

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