这是一个有状态的类,但是它表示类在scala中应该是无状态的,而有状态对象在多线程环境中可能会出错。那么有人可以帮助将其转变为无国籍阶层吗?
trait SwitchStrategy {
def shouldSwitch: Boolean
}
object Strategies {
def countdown(counts: Int): SwitchStrategy = {
return new SwitchStrategy {
private[this] var count = 0
override def shouldSwitch: Boolean = {
count += 1
return if (count >= counts) {
count = 0;
true
} else false
}
}
}
}
答案 0 :(得分:2)
你的整个问题都是建立在保持状态的基础之上,并且没有“魔法语法”#34;消除它。方法yast
不是引用透明的:
shouldSwitch
如果你想使用功能范例,采用使用可变状态并重写的命令式解决方案并不是一个好方法。我不知道你的程序的外部细节,所以我真的无法改变它。您显然需要做的第一件事是删除val s = Strategies.countdown(3)
println(s.shouldSwitch) // false
println(s.shouldSwitch) // false
println(s.shouldSwitch) // true
所依赖的可变状态。一个常见的解决方案是将调度程序的状态信息提供给负责人,这在这种情况下意味着SwitchStrategy
的调用提供了计数。
答案 1 :(得分:1)
处理状态的全功能方法称为状态monad。
此处提供了更多信息:http://eed3si9n.com/learning-scalaz/State.html或此处:http://timperrett.com/2013/11/25/understanding-state-monad/
没有语法或简单的重构可以让您从一种风格转换到另一种风格。
简单来说:
为了达到预期的结果,而不是修改内部状态,每个操作都应返回一对(Result, NewState)
,并且在连续操作中,您应该丢弃先前的状态并使用新返回的状态。
答案 2 :(得分:1)
(可变)国家总是不好,有时是不可避免的。迭代器具有状态,I / O流也是如此...尝试在没有它们的情况下编写有用的东西。 它也不一定会在多线程环境中出错。" ...尤其是,如果你不在线程之间分享你的州长。
话虽如此,无状态(或相当引用透明)代码更容易推理,因此往往更可靠和更健壮。所以,当你可以绕过"天真的"要求拥有国家,通常是一个好主意。
在这种情况下,我认为,这样的事情可能有用:
trait SwitchStrategy {
def shouldSwitch: Boolean
def next: SwitchStrategy
@tailrec
final def apply[T](strategy: T => T)(initial: T): T =
if(shouldSwitch) initial else next(strategy)(strategy(initial))
}
case class CountDown(n: Int) extends SwitchStrategy {
def next = n match {
case 0 => this
case _ => copy(n-1)
}
def shouldSwitch = n == 0
}
然后您可以像这样使用它:
def makeZero = CountDown(10) { n:Int => n - 1 } (10)
def plus(a: Int, b: Int) = CountDown(a) { n: Int => n + 1} (b)
def pow(a: Int, b: Int) = CountDown(b-1) { n: Long => n * a } (a)
等