Skip to content

Instantly share code, notes, and snippets.

@kmizu
Created March 13, 2012 12:48
Show Gist options
  • Save kmizu/2028558 to your computer and use it in GitHub Desktop.
Save kmizu/2028558 to your computer and use it in GitHub Desktop.
Minimal implementation of amb by shift/reset

↑のambの動作原理

  • ポイントは、ambの中のshiftでキャプチャされた継続kを呼び出すと、resetに渡された式を最後まで評価した後、kの呼び出し元に戻ってくる事。基本的に↓という感じ。
  1. a = amb(1, 2, 3)
  2. shift{k:(Int => Unit) => elements.foreach(k)}
  3. foreach x in (1, 2, 3) 1. k(x)が呼び出されるて、shiftからxが返る(==> aがxに束縛される) 2. block { ... } の最後まで評価した後、k(x)の呼び出し元、つまりforeachの内側に戻ってくる
  4. b = amb("A", "B", "C")
  5. shift{k:(String => Unit) => elements.foreach(k)}
  6. foreach y in ("A", "B", "C") 1. k(y)が呼び出されて、shiftからxが返る(==> bがyに束縛される) 2. block { ... } の最後まで評価した後、k(y)の呼び出し元、つまりforeachの内側に戻ってくる
//scalac -P:continuations:enable
import scala.util.continuations._
object Amb{
def amb[T](elements: T*):T @suspendable = shift{k:(T=>Unit) => elements.foreach(k)}
def block(body : => Unit @suspendable): Unit = reset(body)
def main(args: Array[String]) {
block {
val a = amb(1, 2, 3)
val b = amb("A", "B", "C")
println(a, b)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment