Brock Wilcox > Coro-Generator-0.3.0 > Coro::Generator

Download:
Coro-Generator-0.3.0.tar.gz

Dependencies

Annotate this POD

View/Report Bugs
Module Version: 0.3.0   Source  

NAME ^

Coro::Generator - Create generators using Coro

SYNOPSIS ^

  use strict;
  use Coro::Generator;

  my $even = generator {
    my $x = 0;
    while(1) {
      $x++; $x++;
      yield $x;
    }
  };

  # This will print even numbers from 2..20
  for my $i (1..10) {
    print $even->() . "\n";
  }

DESCRIPTION ^

In the words of wikipedia, generators look like functions but act like iterators.

WHY USE THIS? ^

My own use of this is for a technique called 'Inversion of Control'. The idea is to let one piece of the program think it's in control even though it isn't. Though it is true that this sort of psychological warfare with the beliefs of your code can be mind-bending, if you go with the flow (HAHAHA) it can often make for much more readable code. Google up the 'actor model' or something like that if you want some further thoughts on that.

So, for the sake of illustration, let's rename yeild to gimme_more_input in this example:

  use Coro::Generator qw( generator gimme_more_input );

  my $processor = generator {
    my $i = 0;
    while(1) {
      my $input = gimme_more_input($i);
      $i += $input;
    }
  };

  sub count_jump {
    my $current_count = shift;
    print "Count: $current_count\n";
    print "Add to that: ";
    my $add = <>;
    chomp $add;
    return $add;
  }

  my $count = $processor->();
  while(1) {
    my $addsome = count_jump($count);
    $count = $processor->( $addsome );
  }

... note that the generator thinks that it is the thing looking and getting input, when in fact it is the main while loop that is actually looping and getting input. Noodle that a bit.

EXPORTS ^

The generator and yeild functions are exported by default. They can be imported as a different name by passing the names in as arguments to the use statement, e.g.

  use Coro::Generator; # import 'generator' and 'yield'
  use Coro::Generator qw( generator yield ); # ditto
  use Coro::Generator qw( fiber yield ); # import it as fiber

Calling yield outside (the execution of) a generator will likely do horrible things. So... don't do that.

SUBROUTINES ^

$g = generator { ... };

This creates a generator, and assigns it to $g. It is kinda like a subref:

  $f = sub { ... }

except it needs a ';' at the end. This generator can be invoked just like a subref, but it has added ability to remember it's full state between invocations -- including not only lexical variables but also where it was in its computation (control flow state). So if you have:

  $count = generator {
    my $i;
    while(1) {
      yield $i++
    }
  };

You get a generator named $count. You can call it over and over again, just like a normal subref, but each time you call it you'll get one bigger number than the time before.

@new_params = yield( $return_value );

When you are ready to return an intermediate result from within your generator, use yeild. I read it as "I am YIELDING my current result". It's kinda like return... but it isn't the end of your subroutine.

When someone invokes your generator again they can pass in some more parameters, just like when they called it the first time. Whatever they pass in is returned by your yield call.

SEE ALSO ^

Coro

AUTHOR ^

Brock Wilcox, <awwaiid@thelackthereof.org>

COPYRIGHT AND LICENSE ^

Copyright (C) 2010 by Brock Wilcox

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.12.1 or, at your option, any later version of Perl 5 you may have available.

syntax highlighting: