5

再帰はクールですが、高階ライブラリ関数に囲まれている場合は低レベルです。最後に生成された値に依存するプロセスの再帰関数を記述しないようにしています。

私は通常iterate、最後の値と現在のパラメーターの「zip形式」リストに対してClojureの関数を使用します。ScalaのコレクションAPIに同等の関数はありますか?

これは、いくつかのクレイジーな擬似コードの抽象的な例の試みです。

あなたが持っていると言う

  • 入力リスト:Seq(1,2,3)
  • 生成された最後の値とリスト内の次の項目に対して実行するアクション:

    lastValue ^ 2 + nextInt(i)

生成されたすべての値を累積する必要があります。

私は次のようなものを書かないようにしています:

def f(ls:Seq[Int]):Seq[Float] = {

  def g(pos:Int, lastGen:Float):Seq[Float] = { 
    val v = gen(lastGen, ls(pos))
    if( end(v) )
      Seq(v)
    else
      Seq(v) ++ g(pos+1, v)
  }

  f(0, 1)
}

Haskellでフィボナッチのレイジーストリームバージョンを定義するのに似たようなものを見たので、仮想的にはそれ自体を参照するレイジーストリームを使用できますが、Clojureの反復よりも脳を包み込むのは困難です。

4

3 に答える 3

6

これはあなたが探しているものですか?iterateこれは基本的にClojureと同じです。

List.iterate(1, 5) { _ + 1 }
// res1: List[Int] = List(1, 2, 3, 4, 5)

iterateforの定義はListから来ていると思いますGenTraversableFactory

唯一の欠点は、2番目の引数が必要な引数の数であるため、Clojurelenのように無限のシーケンスを返さないことです。iterate

アップデート:

何か新しいことを学びました!Streamオブジェクトにもiterateメソッドがあり、これにより無限のレイジーストリームを作成できます。

(Stream.iterate(1) { _ * 2 } take 5).toList
// res1: List[Int] = List(1, 2, 4, 8, 16)
于 2012-08-23T03:54:05.267 に答える
3

表示したコードは、基本的に次のようなものと同等です。

ls.foldLeft(List(1.0))((a, b) => gen(a.head, b) :: a).reverse
于 2012-08-23T04:04:18.153 に答える
0

必要な高階関数は、のように聞こえscanLeftます。これは、中間ステップを記憶するフォールドのようなものです。たとえば、次のようなものがあるとします。

val ls = Seq(1, 2, 3)
def gen(lastValue: Double, n: Int) = math.pow(lastValue, 2) + n

次に、次のようにそれらを組み合わせることができますscanLeft

scala> ls.scanLeft(1.0)(gen)
res0: Seq[Double] = List(1.0, 2.0, 6.0, 39.0)

これは、Apocalispのの定式化とほぼ同等ですが、中間値を保持するfoldLeft点が異なりscanLeftます。

于 2012-08-23T12:16:07.587 に答える