3

より機能的なスタイルで書き直そうとしている変更可能なスカラ コードがいくつかあります。これはかなり複雑なコードなので、少しずつリファクタリングしようとしています。私の最初の考えはこれでした:

def iterate(count:Int,d:MyComplexType) = {
  //Generate next value n
  //Process n causing some side effects
  return iterate(count - 1, n)
}

iterate(2000000,initialValue)

コード全体にまだ副作用が混在しているため、これはまったく機能していないように見えました。私の2番目の考えはこれでした:

def generateStream(d:MyComplexType):Stream[MyComplexType] = {
  //Generate next value n
  return Stream.cons(n, generateStream(n))
}

for (n <- generateStream(initialValue).take(2000000)) {
  //process n causing some side effects
}

少なくとも、機能的な値生成コードを変更可能な値処理コードから分離したため、これは私にとってより良い解決策のように思えました。ただし、実際には保存する必要のない大きなリストを生成しているため、これはメモリ効率が大幅に低下します。

これにより、3つの選択肢が残ります。

  1. 末尾再帰関数を作成し、弾丸をかじって値処理コードをリファクタリングする
  2. 遅延リストを使用します。これはメモリに敏感なアプリではありません (ただし、パフォーマンスには敏感です)。
  3. 新しいアプローチを思いつく。

私が本当に欲しいのは、処理後に値を破棄できる遅延評価シーケンスだと思います。助言がありますか?

4

2 に答える 2

6

パフォーマンスが重要なアルゴリズムは、多くの場合、ミュータブルな方がうまく機能することに注意してください。時期尚早の最適化解除に注意してください。

Scala 2.8 ではIterator.iterate、値を格納せずに無限シーケンスを作成するために使用できます。しかし、それだけでコードをより機能的にリファクタリングするための重要なステップになるかどうかはわかりません。トリッキーなのは、「副作用のあるデータを処理する」部分です。

すべてを反復ブロックに入れることができます。

Iterator.iterate(initialState)(x => {
  // create a new state based upon state x
}).drop(2000000).next

ここで、初期状態を順次変更することにより、無限の処理ストリームを定義しました。最初の 2000000 個の値 (そのうちの 1 つは初期値) を破棄し、次の値 (2000000 番目に生成された値) を取得します。0 と x=>x+1 で試してみて、動作を確認してください。

于 2010-05-13T19:21:50.583 に答える
3

Range0 から 2000000 までの int の Seq を作成するだけの場合に使用したいと考えています。少なくとも 2.7 では、これは素晴らしく怠惰です。

于 2010-05-13T18:12:56.370 に答える