(* * This program allows the user to interactively put numbers on two streams. * Several other streams are concurrently produced by different combinations * of those two streams (addition, zipping, mapping, etc.). All streams are * displayed in the Inspector. *) import structure Inspector from "x-alice:/lib/tools/Inspector" open Promise fun build f x = let val p = promise () in spawn f (x,p); future p end fun continue x p = let val p' = promise () in fulfill (p, x::future p'); p' end fun finish p = fulfill (p,nil) fun plus xsys = build plus' xsys and plus' ((x::xs, y::ys), p) = plus' ((xs,ys), continue (x+y) p) | plus' ( _, p) = finish p fun zip xsys = build zip' xsys and zip' ((x::xs, ys), p) = zip' ((ys,xs), continue x p) | zip' ( _, p) = finish p fun map f xs = build (map' f) xs and map' f (x::xs, p) = map' f (xs, continue (f x) p) | map' f ( nil, p) = finish p fun main() = let val p1 = promise () val p2 = promise () val A = future p1 val B = future p2 val AplusB = plus (A,B) val AzipB = zip (A,B) val AtoChar = map (str o chr) A val Bdiv10 = map (fn n => real n / 10.0) B in Inspector.inspect {A, B, AplusB, AzipB, AtoChar, Bdiv10}; loop (p1,p2); OS.Process.exit OS.Process.success end and loop pp = ( TextIO.print "Enter \"k n\" to put number n on stream k (k=1,2)\n" ; loop' pp ) and loop' (p1,p2) = case (TextIO.print "> "; TextIO.inputLine TextIO.stdIn) of NONE => () | SOME "\n" => loop' (p1,p2) | SOME s => case String.tokens Char.isSpace s of ([] | [_] | _::_::_::_) => loop (p1,p2) | [s1,s2] => case (Int.fromString s1, Int.fromString s2) of (SOME (k as (1|2)), SOME n) => let val p' = promise () in if k = 1 then (fulfill (p1, n::future p'); loop' (p',p2)) else (fulfill (p2, n::future p'); loop' (p1,p')) end | _ => loop (p1,p2) val _ = main()