2011-07-07 8 views
3

時には、関数から変更可能なコレクションをシーケンスとして返したいことがあります。アップキャストはseq<_>になりますが、シーケンスはダウンキャストと変更が可能です(通常は重要ではありません)。おそらく、そのような関数を書くの他の方法、どのようになるか、主に好奇心(と楽しみ)のためシーケンスで可変コレクションを折り返す

let wrap items = Seq.map id 
let wrapDict dict = Seq.map ((|KeyValue|) >> snd) 

:私のいつものソリューションを次のように上昇を与えているラップなど-シーケンス機能を使用することですより慣用的で簡潔な、あるいは演技的な方法ですか?

+0

'ReadOnlyCollection <_>'に変更可能なコレクションをラップしてからシーケンスとして返すのはどうでしょう? – ildjarn

答えて

5

Seq.readonlyは、探している機能です。

+0

うん、完璧です。なぜ私はそれを見たことがないのか分からない。 – Daniel

2

私はStephanによって提案された機能がおそらくあなたが探しているものだと思います。

しかし、Seq.readonly機能(ReadOnlyCollectionまたはSeq.mapを含む)は、外から突然変異することができないように配列をラップします。結果のシーケンスは、オブジェクトによって変異させることができるので、しかし、それはまだ非常に微妙な振る舞いを持っています

type Arr() = 
    let data = [| 1 .. 5 |] 
    member x.ItemsSeq = Seq.readonly data 
    member x.Mutate() = data.[0] <- 10 

let a = Arr() 
let s = a.ItemsSeq 
printfn "%A" (s |> List.ofSeq) // [1; 2; 3; 4; 5] 
a.Mutate() 
printfn "%A" (s |> List.ofSeq) // [10; 2; 3; 4; 5] 

私は、これは(主に関数型言語では)非常に予期しない動作であると思うだろう。

内部コレクションが変更可能な場合は、後で変更できないデータの完全なクローンを作成し、返されたシーケンスが常に同じ結果を返すようにすることも考えられます。例えば、data |> Array.ofSeq |> Seq.readonly

+0

+1良い点は、インプレース変更を内部的に含む単一の配列を使用する辞書順列を生成する実装では、このアプローチを使用する必要がありました。http://projecteulerfun.blogspot.com/2010/06/problem- 42-what-is-largest-n-digit.html –

+0

@Tomas:知っておくべきことです。ありがとう。 – Daniel

関連する問題