So, the return in pointy sub thread got me thinking about useful uses of return
in pointy subs that involve being able to return multiple times. And this is
what I came up with, it's an implementation of 'choose':

    my &give_up = sub { fail "Ran out of choices" }

    sub choose ([EMAIL PROTECTED]) {
      my &old_give_up = &give_up;
      my $try = -> @choices {
        if [EMAIL PROTECTED] { &give_up = &old_give_up; give_up }
        else {
          my ($choice, @newchoices) = *choices;
          &give_up = -> { return $try(@newchoices) }
          $choice;
        }
      }
      $try(@all_choices);
    }

How do you use that I hear you ask:

    my $x = choose(1,3,5);
    my $y = choose(1,5,9);

    # say "Trying $x * $y"; # Uncomment for an insight into how this works.
    give_up unless $x * $y == 15;
    say "Found $x * $y = 15";

Yes, that is an artificial example.

If you can't use a returning pointy block more than once, then this becomes:

    sub callcc (Code &block) { &block(&?CALLER_CONTINUATION) }

    my &give_up = sub { fail "Ran out of choices" }

    sub choose ([EMAIL PROTECTED]) {
      callcc -> &cnt {
        my $try = -> @choices {
          if [EMAIL PROTECTED] { &give_up = &old_give_up; give_up }
          else {
            my ($choice, @newchoices) = *choices;
            &give_up = sub { cnt($try(@newchoices)) };
            $choice;
          }
        }
        $try(@all_choices);
      }
    }

Tracing the flow of control in both these examples is left as an exercise for
the interested reader.

The only catch is, neither of them works in Pugs. Yet.
        

Reply via email to