2

在我的 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!

whereParse是一个函数对象,它有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) }

}

诀窍是infoanderror方法的输出应该以某种方式对Parse对象来说是本机的,并通过如上所示的示例构造消息。因此,他们

  1. 必须像示例中一样可访问,无需任何导入。
  2. 必须有权访问传递给的第一个参数Parse()(示例中为“TYPE”)。
  3. 在工作期间不得创建任何实例或额外对象。

这是一个理想的描述。我认为这将需要更多样板文件。请建议,我怎样才能做到这一点?

编辑:我最初的猜测是在方法中声明infoanderror方法apply并没有使它们在parseF传递的方法中可见。嗯,不出所料..

4

2 回答 2

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 {}

于 2012-09-19T11:29:26.927 回答
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 => {

})
于 2012-09-19T12:12:14.970 回答