2017-11-07 14 views
1

私はKotlinで関数型プログラミングを採用しようとしています。可能であれば、可変のvarsの使用は避けてください。通常、ユニット返す関数のad hocテストでは、関数内で何かが正常に機能しているかどうかを確認するために、ちょうどprintln()があります。しかし、このテストでは、文字列を累積して、最終的にassertEquals(...)を使用する必要があります。コトリンのユニット機能内に蓄積する機能的な方法は?

いつものように、囲いの範囲でvarと宣言し、+=を使ってそれに蓄積しています。 関数を渡したり連鎖したり、変更可能なvarを削除したりすることで、より機能的な方法がありますか?は、ここではいくつかの単純化されたが、説明のコードです:

inline fun <T> Iterable<T>.forEachFrom(beg:Int, act:(T)->Unit) { 
    var i=0; if (beg>=0) for (e in this) if (i++ >= beg) act(e) 
} 

fun main(args:Array<String>) { 
    val l = listOf("zero", "one", "two", "three", "four") 

    // print-to-screen test 
    l.forEachFrom(2){print("$it-")}; println() 
    // output: two-three-four- 

    // accumulate-in-var test 
    var s = "" 
    l.forEachFrom(2){s += "$it-"}; println(s) 
    // output: two-three-four- 

    // Is there a purely functional way, without declaring a mutable var? 
    // val s = l.forEachFrom(2){accumulator???("$it-")} 
    // - OR - 
    // val s = l.forEachFrom(2).accumulator???("$it-") 
    // println(s) 
} 

答えて

3

のみkotlin-STDLIBと同じことを行うと、コードの意味を保持する方法(すなわち、一度だけ反復)convert the Iterable<T> to Sequence<T>にあると.drop(n)拡張子を使用します。

inline fun <T> Iterable<T>.forEachFrom(beg: Int, act: (T) -> Unit) = 
    if (beg >= 0) 
     asSequence().drop(beg).forEach(act) else 
     Unit 

UPD:全体的な質問を議論した後、我々は別のアプローチを思い付きました。

あなただけのコールバックを受け入れますが、何も返さないアイテムを反復処理し、カスタム高次機能を持っている場合は、あなたがbuildSequence { ... }を使用して、コールバックとしてyield(it)を渡すことでSequence<T>にそのカスタム反復ロジックをラップすることができます

val sequenceFromCustomFunction = buildSequence { 
    l.forEachFrom(2) { yield(it) } 
} 

これは、あなたが機能的なスタイルで、この順序で作業することを可能にすると、特に、順序を折る:

val s = sequenceFromCustomFunction.fold("") { acc, it -> acc + it + "-" } 
+0

おかげで...私はおそらくより良いforEachFrom exampが出ているはずですル。 :)私はその関数を改良しようとはしていませんが、純粋に機能的な方法でユニット返す関数内にテスト文字列を蓄積できるかどうかをもっと理解しようとしています。私はテストを書くために必要な、より複雑な 'Unit'を返す関数をたくさん持っています。ここで 'var s'の良い選択肢がないかどうかについて、私の心を引き伸ばすことは、もっと練習です。 – sirksel

+0

@sirksel、基本的に、機能的なスタイルで状態を蓄積するには、通常、* fold *イディオムを使用します(['fold'拡張機能があります)(https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections /fold.html)をKotlinに掲載)。 – hotkey

+0

@sirksel、上記の関数を 'fold'で実装した例です:[(gist)](https://gist.github.com/h0tk3y/20f7985c79f746e91312e375de571dbb) – hotkey

関連する問題