Dear all,

I just learned about an interesting programming paradigm
called Functional Reactive Programming.  This is like
functional programming except that each function can
accept a stream of input values.  If a new input value
arrives on an argument, then the function is reevaluated
with all the most recent input values and a new output
value is created.  This is a kind of dataflow
programming.  It can handle nondeterminism, so it is
more expressive than declarative concurrency.  In fact,
it can be implemented with the declarative concurrent
model extended with WaitTwo.  (This means that it is
similar in expressiveness to concurrent logic
programming!)

Here is an example.  Assume that 'Add' creates an
addition that accepts streams (I will show in a minute
how to define Add).

% The expression a=b+(c+1) where a, b, c are streams
declare As Bs Cs in
As={Add Bs {Add Cs 1}}
{Browse As}
{Browse Bs}
{Browse Cs}

% Let's put a few elements on the input streams
Cs=2|_
Bs=1|2|3|4|_
% Now As becomes 4|5|6|7|_

% Extending Cs will cause As to be extended
Cs=2|3|_
% Now As becomes 4|5|6|7|8|_

% Extending Bs will cause As to be extended
Bs=1|2|3|4|5|6|_
% Now As becomes 4|5|6|7|8|9|10|_

% If a stream terminates, then no more values will appear on it
Bs=1|2|3|4|5|6|nil
% The 'Add Bs' operation will now always add 6 to its input
Cs=2|3|4|5|_
% Now As becomes 4|5|6|7|8|9|10|11|12|_

% If both Cs and Bs are terminated, then so will As
Cs=2|3|4|5|nil
% Now As becomes 4|5|6|7|8|9|10|11|12|nil

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Here is how to define Add

% TwoArgOp is a generic function that can be used to define any
% two-argument FRP operation.  The FRP operation accepts a single
% integer or a stream of integers.  Termination of the stream is
% handled correctly: when a stream terminates with nil then there
% are no more changes on that stream.

declare
% Waits until at least one argument is bound
% Fairly returns 1 if X is bound or 2 if Y is bound
fun {WaitTwo X Y}
  {Record.waitOr X#Y}
end

declare
fun {TwoArgOp F}
  fun {$ As Bs}
     thread
        fun {OpLoop Aval Bval As Bs}
           case {WaitTwo As Bs}
           of 1 then
              case As of A|Ar then {F A Bval}|{OpLoop A Bval Ar Bs}
              [] nil then {Map Bs fun {$ B} {F Aval B} end}
              end
           [] 2 then
              case Bs of B|Br then {F Aval B}|{OpLoop Aval B As Br}
              [] nil then {Map As fun {$ A} {F A Bval} end}
              end
           end
        end
        fun {FirstValue As}
           case As of A|Ar then A#Ar else if {IsInt As} then As#nil end end
        end
        % Wait until each stream has its first value
        Aval#Anext={FirstValue As}
        Bval#Bnext={FirstValue Bs}
     in
        % Execution loop
        {F Aval Bval}|{OpLoop Aval Bval Anext Bnext}
     end
  end
end

declare
Add={TwoArgOp fun {$ A B} A+B end}




_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to