Skip to content

Instantly share code, notes, and snippets.

@einblicker
Created November 11, 2011 23:51
Show Gist options
  • Select an option

  • Save einblicker/1359705 to your computer and use it in GitHub Desktop.

Select an option

Save einblicker/1359705 to your computer and use it in GitHub Desktop.
dynamic scope emulation by reader monad
import scalaz._
import Scalaz._
import util.continuations._
import collection.mutable.LinkedHashMap
object DynamicScopeEmulation extends App {
//see also: https://gist.github.com/1338773
object ReifyReflect {
def reify[M[_] : Monad, A](body: => A @cps[M[A]]): M[A] =
reset{val result: A = body; implicitly[Monad[M]].pure[A](result)}
implicit def monad2reflect[M[_] : Monad, A](action: M[A]) = new {
def reflect[B]: A @cps[M[B]] =
shift{(k: A => M[B]) => implicitly[Monad[M]].bind(action, k)}
}
}
object ReaderMonad {
type Env = LinkedHashMap[String, Any]
class Reader[A](f: Env => A) {
def apply(env: Env): A = f(env)
}
implicit def readerMonad: Monad[Reader] = new Monad[Reader] {
def pure[A](x: => A) = new Reader(_ => x)
def bind[A, B](a: Reader[A], f: A => Reader[B]): Reader[B] = {
new Reader[B](env => f(a(env))(env))
}
}
def ask = new Reader(identity)
def local[A](f: Env => Env, c: Reader[A]) =
new Reader(e => c(f(e)))
}
//reference page: https://sites.google.com/site/scalajp/home/scala-tips/dynamic_variable
object JsonBuilder {
import ReifyReflect._
import ReaderMonad._
def json(x: => Env @cps[Reader[Env]]): Env = {
reify(x).apply(LinkedHashMap())
}
class ArrowOperatorExtension(key: String) {
def ->(value: Any): (String, Any) @cps[Reader[Env]] = {
val result = (key, value)
val status = ask.reflect[Env]
status += result
result
}
}
def %(children: => (String, Any) @cps[Reader[Env]] ): Env @cps[Reader[Env]] = {
local(_ => LinkedHashMap(), reify{
children
ask.reflect[Env]
}).reflect[Env]
}
def $(elements: Any*): List[Any] = elements.toList
implicit def string2ArrowOperatorExtension(key: String)
: ArrowOperatorExtension = {
new ArrowOperatorExtension(key)
}
}
import JsonBuilder._
val obj = json{%{
"X" -> 1
"Y" -> 2
"Z" -> 4
"nums" -> $(1, 2, 3, 4, 5,
%{"hoge" -> 1; "foo" -> 2})
}}
println(obj)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment