#! perl -w use strict; sub uFIFO { =pod uFIFO - a FIFO that retains only unique values with the ability to iterate (with multiple independant iterators) implemented using closures. One copy of any value except undef will be retained. Calling syntax: my $fifo = uFIFO(); my $count = $fifo{add}( @list ); # counts only unique values added. my $iter1 = $fifo{iterator}(); # Values added whilst the iterator is active my $iter2 = $fifo{iterator}(); # are handled correctly my $first = $iter1{first}(); # Resets to the oldest value (and returns it) my $next = $iter{next}(); # get the next or undef my @unique= $fifo{all)(); # all entries, undefined order my $unique= $fifo{all}(); # Size of the fifo my $sorted= $fifo{ordered}(); # All in fifo order (scalar context as above) =cut my (%fifo, @fifo); return { # Push input item or list onto the fifo, return the number of items added add => sub { return scalar grep { defined $_ && !exists $fifo{ $_ } and push @fifo, \($fifo { $_ } = $_ ); } @_; }, # returns an indepentent iterator for the fifo, iterator => sub { my $next = 0; return { # resets the iterator and returns the first item (Doesn't increment!) first => sub { return scalar @fifo ? ${ $fifo[ $next = 0 ] } : undef; }, # get the next item from the fifo, #or resets and returns undef if at no more next => sub { return scalar @fifo && $next < @fifo? ${ $fifo[$next++] } : undef; }, }, }, # returns all the values from the fifo # (in a non-determinant order (efficiently)) in a list context # or a count of them in a scalar context all => sub { return keys %fifo; }, # returns all the values in the order in which they were added # earlier values remain in place. Later duplicates do not cause promotion. ordered => sub { return map { ${ $_ }} @fifo; }, } }