Clojure には、一時的なコレクションという非常に優れた概念があります。Scala (または F#) 用のものを提供するライブラリはありますか?
3 に答える
これは、F# のような言語の非常に優れた概念のように思えます。興味深いリンクをありがとう!
配列を使用してプログラミングする場合、F# プログラマーはまったく同じパターンを使用します。たとえば、変更可能な配列を作成し、命令的に初期化し、それを返し、次のような不変として扱う関数を使用して操作します(ただし、一時的な配列Array.map
がないため、配列は実際には変更できます)。
seq<'a> 型の使用:同様のことを行う 1 つの方法は、データ構造をseq<'a>
不変データ型であるジェネリック シーケンス ( ) に変換することです。そのため、 を介して元のデータ構造を (直接) 変更できませんseq<'a>
。例えば:
let test () =
let arr = Array.create 10 0
for i in 0 .. (arr.Length - 1) do
arr.[i] <- // some calculation
Array.toSeq arr
良いことは、変換が通常 O(1) であることです (配列/リスト/..seq<'a>
インターフェイスとして実装するため、これは単にキャストされます)。ただし、seq<'a>
ソース コレクションのプロパティ (効率など) は保持されず、(Seq
モジュールから) シーケンスを操作するための汎用関数を使用してのみ処理できます。ただし、これは比較的一時的なコレクションのパターンに近いと思います。
同様の .NET 型もReadOnlyCollection<'a>
、コレクション型 ( よりもやや強力seq<'a>
) を不変のラッパーにラップし、コレクションを変更する操作で例外がスローされます。
関連する型:より複雑な型のコレクションの場合、F#/.NET には通常、可変実装と不変実装 (F# ライブラリに由来する不変実装) の両方があります。通常、タイプはまったく異なりますが、共通のインターフェースを共有する場合があります。これにより、ミューテーションを使用するときに 1 つの型を使用し、もう必要ないことがわかっているときに別の型に変換することができます。ただし、ここでは異なる構造間でデータをコピーする必要があるため、変換は間違いなく O(1) ではありません。O(n) と O(n*log n) の間の何かかもしれません。
同様のコレクションの例として、Dictionary<'Key, 'Value>
不変Map<'Key, 'Value>
と可変の組み合わせHashSet<'T>
、または(F# ライブラリからの)SortedSet<'T>
不変の組み合わせが挙げられます。set<'T>
私は F# でこれに関するライブラリを知りません (標準ライブラリには何もありません。シンプルな永続的/不変構造用のライブラリはたくさんありますが、このようなブログを見た覚えはありません)。サードパーティがそのようなライブラリを作成することは素晴らしいことです。Rich Hickey は最近、これらの素晴らしい実用的な (ほとんどの場合) 関数型のデータ構造に関する人物です。私はそのようなものについて読むのが大好きです。
Please have a look at the following post by Daniel Spiewak:
http://www.codecommit.com/blog/scala/implementing-persistent-vectors-in-scala
He also ported the algorithm by Rich Hickey to Scala. In the article IntMap is also mentioned which is almost as fast the Clojure implementation.