这不一定是 Scala 问题,它是一个设计问题,与避免可变状态、函数式思维等有关。碰巧我正在使用 Scala。
鉴于这组要求:
伪代码:
if (first number == 1) SUCCEED
else if (first number >= 9) FAIL
else {
first = first number
rest = rest of stream
for each (n in rest) {
if (n == 1) FAIL
else if (n == first) SUCCEED
else continue
}
}
这是一个可能的可变实现:
sealed trait Result
case object Fail extends Result
case object Succeed extends Result
case object NoResult extends Result
class StreamListener {
private var target: Option[Int] = None
def evaluate(n: Int): Result = target match {
case None =>
if (n == 1) Succeed
else if (n >= 9) Fail
else {
target = Some(n)
NoResult
}
case Some(t) =>
if (n == t) Succeed
else if (n == 1) Fail
else NoResult
}
}
这会起作用,但对我来说有味道。 StreamListener.evaluate 不是引用透明的。并且使用 NoResult token 感觉不对。它确实具有清晰且易于使用/编码的优点。此外必须有一个功能性的解决方案吗?
我想出了另外两个可能的选择:
我在这里忽略了任何标准的 Scala/FP 习语吗?
最佳答案
考虑到您的第一个可能的选择,我不确定您为什么要将 Result 设为 StreamListener 的子类型,而不是仅将相关的 Result 的特定子类型设为 StreamListener。
sealed trait Result
sealed trait FinalizedResult extends Result
trait StreamListener {
def evaluate(n: Int): Result
}
case object Uninitialized extends Result with StreamListener {
def evaluate(n: Int): Result = {
n match {
case i if (n == 1) => Succeed
case i if (n >= 9) => Fail
case _ => Initialized(n)
}
}
}
case class Initialized(target: Int) extends Result with StreamListener {
def evaluate(n: Int): Result = {
n match {
case i if (n == target) => Succeed
case i if (n == 1) => Fail
case _ => this
}
}
}
case object Succeed extends FinalizedResult
case object Fail extends FinalizedResult
但是,您不是只是将可变性改组到调用代码以跟踪对结果/流监听器的引用吗?
关于scala - 从可变算法中发现函数算法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2806496/