Besides this functional facility, we can also define recursive functions, such as the celebrated Eratosthenes sieve:
let node first x = v where rec v = x fby v let rec node sieve x = let clock filter = (x mod (first x))<> 0 in merge filter (sieve (x when filter)) (true fby false) let node from n = o where rec o = n fby (o + 1) let clock sieve = sieve (from 2) let node primes () = (from 2) when sieve val first : ’a => ’a val first :: ’a -> ’a val sieve : int => bool val sieve :: ’a -> ’a val from : int => int val from :: ’a -> ’a val sieve : bool val sieve :: ’a val primes : unit => int val primes :: ’a -> ’b on sieve
This program is no more real-time since the time and memory to answer at every instant grows.
A compilation option -realtime
is provided for restricting the
language to define only real-time programs.
Here is another way of writing the same program using the implicit filtering of streams done by the pattern matching construct:
let rec node sieve x = let filter = (x mod (first x))<> 0 in match filter with true -> sieve x | false -> true fby false end let node primes () = let nat = from 2 in let clock ok = sieve n in let emit o = n when ok in o val sieve : int => bool val sieve :: ’a -> ’a val primes : unit => int sig val primes :: ’a -> ’b sig
Note that in these two versions, the absence of unbounded instantaneous
recursion is somehow hidden: the program is reactive because the
very first value of filter
is false. Here is a guarded version where
no instantaneous recursion can occur.
let rec node sieve x = automaton Await -> true then Once(x) | Once(i) -> match not_divides_l i x with true -> sieve x | false -> false end end