2016-10-15 125 views
-5

我怎样才能写在常规递归和尾递归下面的函数。斯卡拉递归

def satisfiesAllIt(x: List[Any], test: Any => Boolean): Boolean = { 
    var satisfies = 0 
    for (i <- 0 until x.length) { 
     if (test(x(i))) satisfies += 1 
    } 
    satisfies == x.length 
    } 
+1

你试过了吗?如果是的话,你卡在哪里? – pamu

+0

一个很好的问题。 – Det

回答

2

这是一个基本的递归版本。

def satisfiesAllIt(x: List[Any], test: Any => Boolean): Boolean = 
    if (x.isEmpty) true 
    else if(test(x.head)) satisfiesAllIt(x.tail, test) && true 
    else false 

这是一个尾递归版本。

def satisfiesAllIt(x: List[Any], test: Any => Boolean): Boolean = 
    if (x.isEmpty) true 
    else if(test(x.head)) satisfiesAllIt(x.tail, test) 
    else false 

这就是你在学习标准库之后所做的。

def satisfiesAllIt(x: List[_], test: Any => Boolean): Boolean = x.forall(test) 

@The原型保罗一个好点的(因为他经常做),并提供了另一种选择。

// basic recursive 
def satisfiesAllA(x: List[Any], test: Any => Boolean): Boolean = 
    x.isEmpty || satisfiesAllA(x.tail, test) && test(x.head) 

// tail recursive 
def satisfiesAllB(x: List[Any], test: Any => Boolean): Boolean = 
    x.isEmpty || test(x.head) && satisfiesAllB(x.tail, test) 

什么,我们都在家里跳舞,实际上并没有指出它是基本的和尾递归的定义区别:如果有更多的“工作”的递归调用返回(计算/评估之后进行/ etc。)则是而不是尾递归。

+1

'&& true''只是为了使它不是尾递归而已,有点破解:)如果你想要一个非尾递归的,最好是模拟OP的函数并进行计数? –

+0

@TheArchetypalPaul,我不反对。我认为让这两个版本尽可能相似以便更好地说明核心差异可能会更具启发性。 – jwvh

+1

我不认为它确实说明了区别。 “&& ttrue”不存在任何算法原因'= x,isEmpty || (满足所有(x.tail,test)&& test(x.head))'是一个简洁且非尾递归的verson? –

0

这里是satisfiesAllIt的尾递归版本。这个想法是递归地调用函数,直到列表结束并且如果测试失败返回false

def satisfiesAllIt(x: List[Any], test: Any => Boolean): Boolean = xs match { 
    case Nil => true 
    case x :: xs => 
    if (test(x)) satisfiesAllIt(xs, test) else false 
} 
+0

你不需要数它们。你只需要停止,当第一个不满足 –

+0

@ TheArchetypalPaul你是对的..纠正它:) – pamu

+0

如果你通过'测试'你的'助手'太你发现你不需要辅助功能但可以只有'satisfiediesAllIt' :) –