develooper Front page | perl.perl6.language | Postings from June 2005

Non-deterministic programming in Perl 6

From:
Piers Cawley
Date:
June 9, 2005 14:16
Subject:
Non-deterministic programming in Perl 6
Message ID:
m2u0k7i636.fsf@obelisk.bofh.org.uk
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 (*@all_choices) {
      my &old_give_up = &give_up;
      my $try = -> @choices {
        if !@choices { &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 (*@all_choices) {
      callcc -> &cnt {
        my $try = -> @choices {
          if !@choices { &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.
        



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About