f x (y + 1)
f(x, y + 1)
def factorial(n: Int): Int =
Stream.range(1, n + 1).foldLeft(1)(_ * _)
factorial n =
Stream.fold-left (*) 1 (Stream.range 1 (n + 1))
factorial : Number -> Number
factorial-at : Node -> Number -> Remote Number
factorial-at alice n =
at alice (Remote.pure { factorial n })
.
.
.
.
.
.
-- assuming alice : Node, bob : Node
example : Remote Number
example = do Remote
a := factorial-at alice 3
b := factorial-at bob 7
pure { a + b }
.
.
.
example : Remote Node -> Remote Number
example provision = do Remote
alice := provision
bob := provision
a := factorial-at alice 3
b := factorial-at bob 7
pure { a + b }
.
.
.
.
.
.
.
map-reduce : (a -> Remote b) -> (b -> b -> b) -> b -> Vector a -> Remote b
map-reduce f g z vs = do Remote
bfs := Remote.traverse (a -> Remote.start (f a)) vs
Vector.balanced-reduce (Remote.parallel-map2 g) b bfs
word-count : Text -> Number
word-count txt = ...
distributed-word-count : Remote Node -> Vector Text -> Remote Number
distributed-word-count provision docs =
map-reduce
(doc -> do Remote { n := provision; Remote.at' n { word-count doc }} )
(+)
0
docs
.
.
.
.
.
.
at someNode hugeComputation
.
trait Expr // Vector[Double] => Vector[Double]
case class Num(d: Int, n: Double) extends Expr
case class Plus(d: Int, i: Int, j: Int) extends Expr
case class Decr(d: Int) extends Expr
case class Copy(d: Int, i: Int) extends Expr
case class Block(es: List[Expr]) extends Expr
case class Loop(haltIf0: Int, p: Expr) extends Expr
Num(0, 42) [r0, r1, r2, r3]
==> [42, r1, r2, r3]
.
.
.
.
Plus(0, 1, 2) [r0 , r1, r2, r3]
==> [r1 + r2, r1, r2, r3]
.
.
.
.
Decr(3) [r0, r1, r2, r3 ]
==> [r0, r1, r2, r3 - 1.0]
.
.
.
Copy(1, 2) [r0, r1, r2, r3]
==> [r0, r2, r2, r3]
.
.
.
.
Loop(1, Decr(1)) [r0, 12, r2, r3]
==> [r0, 0, r2, r3]
.
.
.
.
Loop(1, Block(p1, p2 ..)))
.
.
.
// expects `n` in register 0,
// puts result in register 1
val fib = Block( // var n = <fn param>
Num(1, 0.0), // var f1 = 0
Num(2, 1.0), // var f2 = 1
Loop(0, Block( // while (n != 0) {
Plus(3, 1, 2),// val tmp = f1 + f2
Copy(1, 2), // f1 = f2
Copy(2, 3), // f2 = tmp
Decr(0))) // n -= 1
) // }
def interpret(e: Expr, m: Array[Double]): Unit = e match {
case Num(d, n) => m(d) = n
.
...
case Loop(haltIf0, p) => loop(haltIf0, p, m)
}
def loop(haltIf0: Int, e: Expr, m: Array[Double]): Unit =
while (m(haltIf0) != 0) interpret(e, m)
.
.
case Plus(d, i, j) => m(d) = m(i) + m(j)
.
.
.
def loop(haltIf0: Expr, e: Expr, m: Array[Double]): Unit =
while (interpret(haltIf0, m) != 0) interpret(e, m)
.
.
.
.
.
.
.
.
.
case class Plus(..) extends Expr
case class Copy(..) extends Expr
case class PlusThenCopy(..) extends Expr
case class IncrThenDotProductMinus42(..) extends Expr
def interpret(e: Expr, m: Array[Double]): Unit
def interpret(e: Expr): Array[Double] => Unit
def partialEval(e: Expr): Array[Double] => Unit = e match {
case Num(d, n) => m => { m(d) = n }
case Plus(d, i, j) => m => { m(d) = m(i) + m(j) }
case Loop(haltIf0, p) =>
val cp = partialEval(p)
m => while (m(haltIf0) != 0.0) cp(m)
.
.
.
.
.
case Block(es) => es match {
case e :: es =>
val ce = partialEval(e)
val ces = partialEval(Block(ces))
m => { ce(m); ces(m) }
...
}
.
.
.
Array[Double] => Unit
.
def partialEval(e: Expr): Array[Double] => Unit = e match {
case Num(d, n) => m => { m(d) = n }
case Plus(d, i, j) => m => { m(d) = m(i) + m(j) }
case Loop(haltIf0, p) =>
val cp = partialEval(p)
m => while (m(haltIf0) != 0.0) cp(m)
...
.
.
.
Ratio of runtimes, summing 1 million numbers (lower is better)
1.0 Scala
1.85 partially-evaluated (2)
4.03 partially-evaluated
9.77 interpreted
.
.
Array[Double] => Unit
Machine => Unit