我想将一段看起来如下的Java代码转换为Scala:
for (Iterator<Task> it = tasks.iterator(); it.hasNext() && workflow.isAutoRun();) {
Task task = it.next();
if (!runTask(task)) break;
}
我不是scala for-
理解的粉丝(不是我知道如何打破迭代)并且我想出了以下内容:
val completed = tasks.forall { task => workflow.isAutoRun && runTask(task) }
但是,forall
方法的scaladoc如下所示(斜体字):
将谓词
p
应用于此可迭代对象的所有元素并返回true,如果谓词对所有元素都为true
这与我所做的不同(因为它意味着将对每个项目评估谓词,无论先前的评估是否已返回false
)和(实际上)实际上并不等同于forall
方法实际上做了,Iterator
看起来像:
def forall(p: A => Boolean): Boolean = {
var res = true
while (res && hasNext) res = p(next)
res
}
无论如何,我离题了:有没有人对scala代码看起来有什么更好的建议?我希望看到更能传达意图的东西:
tasks.doUntil(t => !isAutoRun || !runTask(t))
答案 0 :(得分:4)
在scala 2.8中,您可以执行以下操作:
breakable{
tasks.foreach{ task =>
if(!(workflow.isAutoRun&&runTask(task))) break
}
}
答案 1 :(得分:4)
与Flaviu上面的答案类似,你可以在某个地方放置隐含的定义:
implicit def conditionalLoop[T](s: Seq[T]) = {
new {
def doWhile(p: T => Boolean): Unit = {
doWhile(s.elements)(p)
}
private def doWhile(it: Iterator[T])(p: T => Boolean): Unit = {
if (it.hasNext && p(it.next)) doWhile(it)(p)
}
}
}
然后,打电话很方便:
tasks doWhile {
t => workflow.isAutoRun && t.run
}
答案 2 :(得分:2)
“exists”返回true,并在谓词返回true后终止循环:
val completed = tasks.exists { task =>
if (workflow.isAutoRun) {
runTask(task)
false
}
else
true
}
编辑:
然后试试这个:
implicit def enrichList[A](list: List[A]) = new {
def doWhile(cond: (A) => Boolean)(body: (A) => Unit) = list exists { x =>
if (cond(x)) {
body(x)
false
}
else
true
}
}
List(1, 2, 3, 4).doWhile(_ <= 3)(println) // prints "1 2 3"
tasks.doWhile(_ => workflow.isAutoRun)(runTask)
答案 3 :(得分:2)
Iterable
的{{1}}:
takeWhile
返回此最长的前缀 可迭代的元素满足 谓词p
param p - 测试 谓语。
<强>返回强> - 此迭代的最长前缀,其元素满足谓词p。
答案 4 :(得分:1)
这会有用吗?
def doWhile[T](iter: Iterator[T])(predicate: T => Boolean): Unit =
if(iter.hasNext && predicate(iter.next()))
doWhile(iter)(predicate)
它的尾部是递归的,所以它不会使堆叠爆炸。由于必须为迭代器的每个元素运行谓词,因此谓词是从T
到Boolean
的函数。
您的代码将缩减为:
doWhile(it) {
task => workflow.isAutoRun &&
runTask(task)
}
由于您的操作具有副作用,因此在评估谓词时已经执行了操作(不是很好,但如果遗留代码的工作方式如此,则必须解决它:)。
更有效的方法是:
def doWhile[T](iter: Iterator[T])(predicate: => Boolean)(action: T => Unit): Unit =
if(iter.hasNext && predicate) {
action(iter.next)
doWhile(iter)(predicate)(action)
}
注意:我可能会发现这个方法的名称比doWhile
更好,但已经晚了......
希望有所帮助:)
- Flaviu Cipcigan