需要 Scala 函数体定义帮助
Scala function body definition help wanted
我正在尝试使用以下语法制作 scala dsl:
val a = Agent() setup { agent => // agent reference.
agent add "Hello World!"
}
a add "Not allowed" // Atm this is allowed.
我可以在设置函数体之外调用方法 add 并调用 add 方法我必须在设置函数体的开头写 agent =>
。
我在atm做过的是trait Agent:
trait Agent {
def setup(f: Agent => Unit): Agent
def add(s: String): Agent
}
case class AgentImpl(strings: Seq[String]) extends Agent {
override def setup(f: Agent => Unit): Agent = {
f(this)
this
}
override def add(s: String): Agent = copy(strings = strings:+s)
}
object Agent {
def apply(): Agent = AgentImpl(Seq.empty)
}
我要做的是:
val a = Agent() setup { // No more references to agent
add "Hello World!"
}
a add "Not allowed" // This mustn't be allowed. Compilation error.
在设置函数主体的开头我没有使用 agent =>
引用代理,如果我尝试在设置函数主体之外进行添加,我会收到错误消息。
这在 Scala 中可行吗?
我可以更改代码的每一部分,添加任意数量的 traits/classes/objects 和其他内容,但不能更改我的 DSL 的语法。
你可以这样做:
sealed trait Agent {
def getFoos: List[String]
def getBars: List[Int]
}
object Agent {
import scala.collection.mutable.ListBuffer
private final class Builder {
private[this] val foos: ListBuffer[String] = ListBuffer.empty
private[this] val bars: ListBuffer[Int] = ListBuffer.empty
private def addFoo(foo: String): Unit = {
foos += foo
}
private def addBar(bar: Int): Unit = {
bars += bar
}
private[Agent] def result(): Agent = new Agent {
override final val getFoos: List[String] =
foos.result()
override final val getBars: List[Int] =
bars.result()
}
}
private[Agent] type BuilderStep = Builder => Unit
object Builder {
private[Agent] def create() = new Builder()
object Steps {
def addFoo(foo: String): BuilderStep =
_.addFoo(foo)
def addBar(bar: Int): BuilderStep =
_.addBar(bar)
}
}
def setup(steps: BuilderStep*): Agent = {
val builder = Builder.create()
steps.foreach(s => s(builder))
builder.result()
}
}
可以这样使用:
import Agent.Builder.Steps._
val agent = Agent.setup(
addFoo("A"),
addFoo("B"),
addBar(1),
addBar(2),
addFoo("C"),
addBar(3),
addFoo("D")
)
但也许传统的不可变构建器同样好用且更简单。
代码运行here.
我正在尝试使用以下语法制作 scala dsl:
val a = Agent() setup { agent => // agent reference.
agent add "Hello World!"
}
a add "Not allowed" // Atm this is allowed.
我可以在设置函数体之外调用方法 add 并调用 add 方法我必须在设置函数体的开头写 agent =>
。
我在atm做过的是trait Agent:
trait Agent {
def setup(f: Agent => Unit): Agent
def add(s: String): Agent
}
case class AgentImpl(strings: Seq[String]) extends Agent {
override def setup(f: Agent => Unit): Agent = {
f(this)
this
}
override def add(s: String): Agent = copy(strings = strings:+s)
}
object Agent {
def apply(): Agent = AgentImpl(Seq.empty)
}
我要做的是:
val a = Agent() setup { // No more references to agent
add "Hello World!"
}
a add "Not allowed" // This mustn't be allowed. Compilation error.
在设置函数主体的开头我没有使用 agent =>
引用代理,如果我尝试在设置函数主体之外进行添加,我会收到错误消息。
这在 Scala 中可行吗?
我可以更改代码的每一部分,添加任意数量的 traits/classes/objects 和其他内容,但不能更改我的 DSL 的语法。
你可以这样做:
sealed trait Agent {
def getFoos: List[String]
def getBars: List[Int]
}
object Agent {
import scala.collection.mutable.ListBuffer
private final class Builder {
private[this] val foos: ListBuffer[String] = ListBuffer.empty
private[this] val bars: ListBuffer[Int] = ListBuffer.empty
private def addFoo(foo: String): Unit = {
foos += foo
}
private def addBar(bar: Int): Unit = {
bars += bar
}
private[Agent] def result(): Agent = new Agent {
override final val getFoos: List[String] =
foos.result()
override final val getBars: List[Int] =
bars.result()
}
}
private[Agent] type BuilderStep = Builder => Unit
object Builder {
private[Agent] def create() = new Builder()
object Steps {
def addFoo(foo: String): BuilderStep =
_.addFoo(foo)
def addBar(bar: Int): BuilderStep =
_.addBar(bar)
}
}
def setup(steps: BuilderStep*): Agent = {
val builder = Builder.create()
steps.foreach(s => s(builder))
builder.result()
}
}
可以这样使用:
import Agent.Builder.Steps._
val agent = Agent.setup(
addFoo("A"),
addFoo("B"),
addBar(1),
addBar(2),
addFoo("C"),
addBar(3),
addFoo("D")
)
但也许传统的不可变构建器同样好用且更简单。
代码运行here.