Scala:将call-by-name变量存储为类字段

时间:2015-05-14 05:08:35

标签: scala dsl callbyname

在我学习Scala的过程中,我尝试使用回调实现一个简单的DSL

object Button {...} // apply 
class Button(val name: String) {
    private val: => Unit; // doesn't work

    def click(f: => Unit) = {
        _click_cb = f
        this
    }

    def onClick() = this._click_cb()
}

Button("Click me!") click {println("Clicked!")}

我创建了一个新对象,将一个回调传递给store。我的演示框架触发onClick方法,该方法应该调用存储的

它适用于() => Unit,但我的DSL看起来很难看:

Button("Click me!") click (() => println("Clicked!"))

当然,我可以做onClick抽象并稍后实现一个匿名类

new Button("Click me!") {def onClick = println("Clicked!")}

但我想玩一些DSL等等

问题是:

  • 如何将f存储在_click_cb
  • 如何提供初始"空" _click_cb的功能?
  • 也许还有更多的scala方法来实现这一目标? (没有匿名课程)

1 个答案:

答案 0 :(得分:2)

一个丑陋的版本只是为了表明lazy val可以保存by name参数值而不进行评估:

case class Button(val name: String) {
  def clickCallback(): Unit = ()

  def click(f: => Unit) = {
    lazy val notEvaluated = f
    new Button(name) { override def clickCallback() = notEvaluated }
  }

  def onClick(): Unit = clickCallback()
}

更清洁,更实用的实施:

class Button(val name: String) {
  def click(f: => Unit) = new Button(name) { override def onClick() = f }

  def onClick(): Unit = ()
}