2016-10-15 3 views
-5

Как написать функцию ниже в регулярной рекурсии и рекурсии хвоста.Scala Recursion

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 || (satisfiesAll (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 Ya вы правы .. исправил его :) – pamu

+0

И если вы передадите 'test' вашему« помощнику », вы обнаружите, что вам не нужна вспомогательная функция но может просто иметь 'satisfiesAllIt' :) –