我目前正试图进入斯卡拉世界。实际上我正在尝试实现没有可变类型的循环策略。
我有一个带有初始主机列表的Scala对象和一个获取下一个主机的方法。
Object RoundRobin {
val optHosts: Option[List[String]] = Option[List[String]]("host1", "host2") // get from Configfile later
var hosts: List[String] = optHosts.getOrElse(List())
def url: String = {
hosts = hosts.tail ++ List(hosts.head)
hosts(0)
}
def execute = ??? // do something with the next host
}
我已经阅读过Scala中的不可变队列,但我真的不知道如何使用不可变类型来解决这个问题。不知怎的,我必须记住一个索引吧?是否是使用不可变类型没有意义的情况之一?
答案 0 :(得分:2)
如果我每次在对象上调用execute时都能正确理解,那么它应该使用不同的元素。然后因为对象必须封装状态,所以无法绕过var
var hosts = collection.immutable.Queue ++ optHosts.getOrElse(List())
def url: String = {
val(element,queue) = hosts.pop
hosts = queue.enqueue(element)
element
}
关于你的问题......
不知何故,我必须记住索引吗?
是的,见上文。但也没有,见下文。
是否使用不可变类型没有意义的情况之一?
取决于。如果你想清楚地保留你的object RoundRobin
,那么这个对象是可变的,你只能在可变的val和不可变的vars之间做出选择。 (你也可以使用指向可变结构的变量,但为什么要这样做呢?)
另一方面,您也可以选择完全不同的方法:
class RoundRobin private(left: List[String], all: List[String]) {
def this(all :List[String]) = this(all, all)
assume(all.nonEmpty)
val theElement = left.headOption.getOrElse(all.head)
def nextRoundRobin = new RoundRobin(if(left.nonEmpty) left.tail else all, all)
def execute = {
// do something with theElement
println(theElement)
// return an object that will execute on the next element
nextRoundRobin
}
}
new RoundRobin(List("1","2")).execute.execute.execute
// prints 1 2 1
当你使用这个版本的RoundRobin时,每次调用execute时它都会给你一个循环对象,它将以循环方式使用下一个元素。 显然,使用RoundRobin的对象可以再次是可变的或不可变的。
答案 1 :(得分:0)
进行了一些细微的改动,以便在执行三次以上的时候交替使用该类,如提供的示例所示。
class RoundRobin private(left: List[String], all: List[String]) {
def this(all :List[String]) = this(all, all)
assume(all.nonEmpty)
val theElement = left.headOption.getOrElse(all.head)
def nextRoundRobin = new RoundRobin(if(left.nonEmpty) left.tail else all.tail, all)
def execute = {
// do something with theElement
println(theElement)
// return an object that will execute on the next element
nextRoundRobin
}
}