2017-10-06 9 views
0

リスト内のブール値の数を数えるこの反復関数があります。Scala再帰的に要素数を指定する述語

def countBoolIter[A](test: A=>Boolean, a: List[A]) = { 
    var count = 0 
    for(elem <- a){ 
     if(test(elem)) count += 1 
    } 
    count 
} 

に渡される最初のパラメータはisBool機能である:関数を呼び出す

def isBool(i: Any) = i match { 
    case _: Boolean => true 
    case _ => false 
} 

は次のようになります。

countBoolIter(isBool, List(1, true, 3, true, false, "hi")) 
// Output: 3 

、私は尾に変換しようとしました再帰型は次のように機能します。

def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match { 
    case Nil => acc 
    case h :: t if(test(h)) => countBoolRec(test, a, acc+1) 
    case h :: t => countBoolRec(test, a, acc) 
} 

ただし、関数が何も返さないため、ランタイムエラーが発生しています。エラーはスローされません。私はそれが何も返されていない無限ループにこだわっていると推測します。

質問:試行された再帰的実装をどのように修正する必要がありますか?

+1

「どのように私は試みた再帰的な実装を修正する必要がありますか?」これは、デバッガでステップインすることで簡単に解決できる問題の1つです。今日、人々はデバッガを使わないのですか?そして、私の芝生から降りてください。 –

答えて

1

機能countBoolRecにエラーがあります:再帰呼び出しで

@tailrec 
    def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match { 
     case Nil => acc 
     case h :: t if(test(h)) => countBoolRec(test, t, acc+1) 
     case h :: t => countBoolRec(test, t, acc) 
    } 

、パラメータとしてトンを使用していないし、何も再び。そうでなければ、基本的に無限ループに入っています。

また、@ tailrecアノテーションを使用して、実装が "tail recursive"であることを確認することをお勧めします。

1

入力と同じリストで繰り返し繰り返しています。

a.headがテストに合格する場合検討:

countBoolRec(テスト、0) countBoolRec(試験1) countBoolRec(試験、2) を...とそう

@scala.annotation.tailrec // Not that your original code wasn't tail-recursive, but it's a generally good practice to mark code that isn't tail recursive with this annotation 
def countBoolRec[A](test: A=>Boolean, a: List[A], acc: Int = 0): Int = a match { 
    case Nil => acc 
    case h :: t if (test(h)) => countBoolRec(test, t, acc + 1) 
    case h :: t => countBoolRec(test, t, acc) 
} 

であなたも同じようにも書くことができますが:

(0 /: a) { (acc, v) => acc + (if (test(v)) 1 else 0) } 
+1

Joke:暗号化者の場合、2番目のオプションはokです。 – angelcervera

関連する問題