Scala DSL - 函数对象的隐式方法

时间:2012-09-19 10:56:55

标签: scala dsl

在我的DSL中,我希望能够这样做:

val a = 5

Parse("TYPE") {
  a match {
    case 3 => info("almost")
    case s: String => error("wrong type")
    case 5 => info("you won!")
    case _ => error("omg")
  }
}

带输出

[INFO] TYPE: you won!

其中Parse是一个函数对象,它具有apply(String)info(String)error(String)方法:

object Parse {

  def apply(name: String)(parseF: => Unit) { parseF }
  def info(text: String) { println("[INFO] " + name + ": " + text) }
  def error(text: String) { println("[ERROR] " + name + ": " + text) }

}

诀窍是infoerror方法的输出应该以某种方式为Parse对象生成,并通过示例构造消息,如上所示。因此,他们

  1. 必须像示例中那样可以访问,不需要任何导入。
  2. 必须能够访问传递给Parse()的第一个参数(示例中为“TYPE”)。
  3. 在工作期间不得创建任何实例或额外对象。
  4. 这是一个理想的描述。我认为它需要更多的样板。请建议,我该如何实现?

    编辑:我在info方法中声明errorapply方法的初步猜测并未在parseF中显示这些方法方法正在通过。嗯,不出所料......

2 个答案:

答案 0 :(得分:2)

也许是这样的:

object Parse {
  val currentName = new util.DynamicVariable("<none>")
  def apply(name: String)(parseF: => Unit) = currentName.withValue(name)(parseF)
  def info(text: String) = println("[INFO] %s: %s" format (currentName.value, text)
}

// usage
import Parse._ // there's no other way to get ability to call 'info' without 'Parse'.
Parse("TYPE") {
  // some code
  info("some info") // prints: [INFO] TYPE: some info
}

info("some other info") // prints: [INFO] <none>: some other info

如果需要,如果info阻止在Parse {}块之外调用,则很容易使{{1}}抛出异常。

答案 1 :(得分:1)

没有满足1-3的解决方案。你可以有1和2或2和3,语法略有不同。

1和2)

class Parse(val s:String) {
  def info....

}

new Parse("TYPE") {

}

2和3)

object Parse {
  def apply(s:String)(f:String=>Unit) = ...
}

Parse("TYPE")(s => {

})