在我的命令式scala代码中,我有一个算法:
def myProcessor(val items: List) {
var numProcessed = 0
while(numProcessed < items.size) {
val processedSoFar = items.size - numProcessed
numProcessed += processNextBlockOfItems(items, processedSoFar)
}
}
我希望保留“块处理”功能,而不仅仅是在项目列表上执行“takewhile”。我怎样才能用函数式重写呢?
最佳答案
所以,这取决于你认为什么更实用,但这里有一个版本没有'var'
def myProcessorFunctional(items: List[Int]) {
def myProcessorHelper(items: List[Int], numProcessed: Int) {
if (numProcessed < items.size) {
val processedSoFar = items.size - numProcessed
myProcessorHelper(items,
numProcessed + processNextBlockOfItems(items, processedSoFar))
}
}
myProcessorHelper(items, 0)
}
(使它成为一个int列表只是为了简单起见,使用一个通用列表会很容易)
我不得不说,这是我不介意可变变量的情况之一——很明显,没有任何对它的引用能逃过方法。
但正如我在上面的评论中所说的,processnextblockofitems本质上是非功能性的,因为它需要它的副作用。一种更实用的方法是它返回到目前为止的处理状态,然后在随后的调用中更新(并返回)这个状态。现在,如果您正在处理两个不同的项列表,您将面临在processnextblockofitems中维护两个不同的部分处理状态的问题…
稍后:
仍然忽略状态问题,一个方便的更改是,如果processnextblockofitems总是处理传递给它的项列表的第一个块,返回它尚未处理的其余项(如果使用list,这是方便和有效的,所以我想知道为什么要使用indicies)。
这会产生如下结果:
def myProcessorMoreFunctional(items: List[Int]) {
if (!items.isEmpty) {
myProcessorMoreFunctional(processNextBlockOfItems(items))
}
}