摘要
昨天在使用scalikejdbc时发现它们用了scala动态特性和宏编程的东西,于是我就有兴趣了解下,并作出总结
昨天在使用scalikejdbc时发现它们用了scala动态特性和宏编程的东西,于是我就有兴趣了解下,并作出总结
class WrapperMapper[M](map: mutable.Map[String,M]) extends Dynamic{ def selectDynamic(name:String):Option[M] = map.get(name) def updateDynamic(name:String)(value:M): Option[M] = map.put(name,value) } val i = new WrapperMapper[Int](mutable.Map("love" -> 2)) println(i.love) i.hate = 5 println(i.hate)
*{{{ * foo.method("blah") ~~> foo.applyDynamic("method")("blah") * foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah")) * foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2)) * foo.field ~~> foo.selectDynamic("field") * foo.varia = 10 ~~> foo.updateDynamic("varia")(10) * foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13) * foo.arr(10) ~~> foo.applyDynamic("arr")(10) * }}}
object Debug { def apply[T](x: => T):T = macro impl def impl(c:blackbox.Context)(x:c.Tree) = { import c.universe._ val q"..$stats" = x val loggedStats = stats.flatMap {stat => val msg = "executing " + showCode(stat) List(q"println(${msg})",stat) } q"..$loggedStats" } }
val n = Debug { val a = 1 val b = a + 2 a + b } println(n)
object TestImpl { def _println[T:c.WeakTypeTag](c:blackbox.Context)(cond:c.Tree) = { import c.universe._ // val Literal(Constant(v:Int)) = cond.tree //这样写编译时就会打印,而不是运行时 q"""${println(cond)}""" } } class PrintA[T] { def myPrint(cond:T):Unit = macro TestImpl._println[T] }
val printA = new PrintA[Int] printA.myPrint(2)
val printA = new PrintA[Int] val x = 2 printA.myPrint(x+2)
def _println[T:c.WeakTypeTag](c:blackbox.Context)(cond:c.Tree) = { import c.universe._ // val Literal(Constant(v:Int)) = cond.tree //这样写编译时就会打印,而不是运行时 // q"""${println(cond)}""" //这样才起作用 q"""println($cond)""" }
println("val a = 1") val a = 1 println("val b = a.+(2)") val b = a + 2 println("a.+(b)") a + b