How many of you have ever thought about how to implement coroutines in Perl?

Wow, I hadn't expected any. How many of you with your hands raised have thought about how you might avoid source filters and evil gotos?

Ok, with the exception of perhaps TheDamian, how many actually tried it? It seemed simple enough and I had a working solution in about 10 minutes:

The problem was that it was fugly and no longer resembled a coroutine. I figured if I put it inside a module (see below), it would hide all the nasty stuff and maybe even make it more useable.

package Iterator; sub TIESCALAR { bless $_[1], $_[0] } sub STORE {} sub FETCH { $_[0]->[1] = 0 if ! $_[0]->[1] || $_[0]->[1] == @{ $_[0]-> +[2] }; $_[0]->[1]++ } package Coroutine; sub new { my $self = bless [[[]]], $_[0]; tie $self->[0][0], 'Iterator', $self->[0]; return $self; } sub add_section { push @{ $_[0]->[0][2] } , $_[1] } sub create { my $s = shift; return sub { $s->[0][2][ $s->[0][0] ]->($s +, @_) } } 42;

Boy was I wrong! It came out horrendous. What, you don't believe me? Just look:

#!/usr/bin/perl use strict; use warnings; use Coroutine; my $coroutine = Coroutine->new(); $coroutine->add_section( sub { my $self = shift; $self->[3] = shift; $self->[4] = \@_; print "$_\n" for @{ $self->[4] }; return $self->[3]++; } ); $coroutine->add_section( sub { my $self = shift; print "$self->[3]\n"; return rand() > .5 ? 'weird' : ++$self->[3]; } ); $coroutine->add_section( sub { my $self = shift; print "The end is near - goodbye cruel "; return pop @{ $self->[4] }; } ); my $wacky = $coroutine->create(42, 'hello', 'world'); print $wacky->(42, 'hello', 'world'), "\n"; print $wacky->(), "\n"; print $wacky->(), "\n"; print $wacky->(), "\n";

All of that to do the following if Perl natively supported coroutines:

coroutine create { my $foo = shift; my @bar = @_; print "$_\n" for @bar; yield $foo++; print "$foo\n"; yield rand() > .5 ? 'weird' : ++$foo; print "The end is near - goodbye cruel "; yield pop @bar; } my $wacky = create(42, 'hello', 'world'); print $wacky->(42, 'hello', 'world'), "\n"; print $wacky->(), "\n"; print $wacky->(), "\n"; print $wacky->(), "\n"; __END__ hello world 42 43 44|weird The end is near - goodbye cruel world 0

Incidently, revdiablo and I came up with a solution using evil gotos and source filters about a week ago that was elegant.

So why post? Well even with the explanation, it isn't easy to see what is going on inside the module - especially with the bless/tie combo. I really didn't intend it to come out obfu. Sometimes obfu just happens

Cheers - L~R

I originally posted this under Obfuscation, but didn't argue with Enlil when he asked to move it here. The real meditation, "Sometimes obfu just happens" along with "sometimes breaking the rules is the best way to do things" is there though - along with an attempt at some humor ;-)

In reply to Obfu Coroutines by Limbic~Region

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.