何らかのデータを蓄積する必要がある場合は、よくあることです。私が慣れている方法は、配列にデータチャンクを追加することです。しかし、これは scala では悪い習慣なので、どうすれば回避できますか?
3 に答える
累積を処理するには、再帰と折りたたみの 2 つの一般的な方法があります。リストの値の合計を計算するために、それぞれの非常に単純な例を見てみましょう。
def sumRecursively(list: List[Int]): Int = {
def recurse(list: List[Int], acc: Int): Int =
if (list.isEmpty) acc
else recurse(list.tail, acc + list.head)
recurse(list, 0)
}
def sumFolding(list: List[Int]): Int =
list.foldLeft(0){ case (acc, n) => acc + n }
これには多くのバリエーションがあり、いずれかのケースをより適切に処理できます。
実際、そうではありません。デフォルトでパッケージVector
の一部である in scala を使用できます。scala.collection.immutable
これにより、追加するたびに新しい (異なる) インスタンスを返す不変のコレクションが作成されます。
詳しくは:
http://www.scala-lang.org/docu/files/collections-api/collections_15.html
最も一般的な用途では、「map」操作と「flatMap」操作を使用してデータ構造を機能的に生成します。どちらも 1 つのデータ構造から開始し、その中の各要素に何らかの操作を適用して、元のデータ構造と同じ形状の新しいデータ構造を返します。それらは、新しいデータ構造がどのように設定されるかだけが異なります。これら 2 つは非常に一般的であり、非常に強力であるため、Scala にはそれらをサポートする特別な構文である for 内包表記が含まれています。for 内包表記は表面的には Java スタイルの for ループに似ていますが、実際には一連の map および flatMap 呼び出しにコンパイルされます (他にもいくつかあります)。
関数型プログラミングでは、データ構造の構築と破棄に必要な手順を明示的に記述するのではなく、問題をあるデータ構造から別のデータ構造へのこのような変換に分解するのが一般的です。これには、特にどのデータ構造から始めるかを理解する際に、慣れる必要があります。一度マスターすると、これは非常に強力なテクニックであり、機能の大部分を明確かつ正確に表現でき、バグが入り込む余地がほとんどありません.
また、"map" と "flatMap" の両方が、実際には別のより強力な関数 "fold" の特殊なケースであることも注目に値します。"fold" (技術的な理由から "foldLeft" と "foldRight" の両方として実装されています) は、データ構造の構築と分解の両方に使用できます。