Scala:将按名称调用的变量存储为 class 字段
Scala: store call-by-name variable as class field
在我学习 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!")}
我创建了一个新对象,将回调传递给它进行存储。我的演示框架触发 onClick
方法,应该调用存储的
它适用于 () => Unit
但我的 DSL 看起来很丑:
Button("Click me!") click (() => println("Clicked!"))
当然,我可以做 onClick
抽象并稍后实现匿名 class
new Button("Click me!") {def onClick = println("Clicked!")}
但我想玩一些 DSL 之类的东西
问题是:
- 如何将
f
存储在 _click_cb
中?
- 如何为
_click_cb
提供初始 "empty" 函数?
- 也许有更多的方法可以实现这一点? (没有匿名 classes)
一个更丑陋的版本只是为了表明 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 = ()
}
在我学习 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!")}
我创建了一个新对象,将回调传递给它进行存储。我的演示框架触发 onClick
方法,应该调用存储的
它适用于 () => Unit
但我的 DSL 看起来很丑:
Button("Click me!") click (() => println("Clicked!"))
当然,我可以做 onClick
抽象并稍后实现匿名 class
new Button("Click me!") {def onClick = println("Clicked!")}
但我想玩一些 DSL 之类的东西
问题是:
- 如何将
f
存储在_click_cb
中? - 如何为
_click_cb
提供初始 "empty" 函数? - 也许有更多的方法可以实现这一点? (没有匿名 classes)
一个更丑陋的版本只是为了表明 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 = ()
}