It occurred to me that being able to set up 'pure' functions in such a
way that they are lazily evaluated when passed a superposition might
be a win.

And then I got to thinking about what would be required from the
language to allow me to implement this functionality in a module. I am
assuming (for the purposes of this example) that functions will get
called with 'simple' argument lists, no defaulting etc, and a maximum
of one superposed argument...)

    class PureFunction is Sub {

      # I'm assuming here that 'apply' is equivalent to func(...)
      method apply(*@arglist) {
        my @curry_list;
        my $super_arg;
        for @arglist; .param_list -> $arg; $param {
          when Superposition { 
            die "Too many superposed args" if defined $super_arg;
            $super_arg = $arg;
          }
          otherwise {
            push @curry_list, ($param.symbol => $arg);
          }
        }
      
        return FunctionApplication::Superposed
                 .new( superposition => $super_arg,
                       func => $self.given(*@curry_list) );
        }
      }
    }

    class FunctionApplication::Superposed is Superposition {
      my $.superposition;
      my $.func;
 
      method force ($self is rw:) {
        return $self = ($.func($.superposition)).force;
      }
 
      method eigenstates {
        .force.eigenstates;
      }
    }

    method Superposition::force ($self:) { $self }

The idea being that, when you do 

    a_pure_func($val1|$val2|$val3)

instead of Perl going away and doing the calculation right away, you
get back a 'special' superposition which stores an 'invocation
description' and calculation is deferred until you need to get a
superposition's list of possible states.

If that were all there were to it of course then there wouldn't be
much gain from doing this, however, consider:

    # Ignore duplicates, it's a proof of concept dammit!
    method FunctionApplication::Superposed::choose {
      loop {
        $.function($.superposition.choose);
        CATCH Exception::SuperPositionExhausted { die $@ }
        CATCH Exception::ChooseFailure { redo }
        otherwise { throw $@ }
      }
    }

    method Superposition::choose($self:) {
      for @.states -> $state {
        when Superposition {
          loop {
            my $val = try { 
              $state.choose;
              CATCH Exception::SuperPositionExhausted { last }
              otherwise { die $@ }
            }
            yield $val;
          }
        }
        otherwise { yield $state }
      }
      throw Exception::SuperPositionExhausted: $self;
    }

And, ooh, look, we have something that'll Do The Right Thing with the
nondeterministic algorithm I posted last week. 

*Damn* but Perl 6 is going to be a potent programming language...
   
                                             

      
        

-- 
Piers

   "It is a truth universally acknowledged that a language in
    possession of a rich syntax must be in need of a rewrite."
         -- Jane Austen?

Reply via email to