开发者

Wrapping a mutable collection with a sequence

Occasionally, I want to return a mutable collection from a function as a sequence. Upcasting to seq<_> works, but the sequence could be downcasted and modified (not that it usually matters开发者_如何学编程). My usual solution is to use a wrap-as-a-sequence function which has given rise to the following:

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

Mostly for curiosity (and fun), what would be other ways of writing such functions, perhaps in a more idiomatic, concise, or performant way?


Seq.readonly is the function you are looking for.


I think that the function suggested by Stephan is probably the thing you're looking for.

However, there is one tricky thing - the Seq.readonly function (as well as ReadOnlyCollection or using Seq.map) wraps the sequence so that it cannot be mutated from the outside. However, it still has quite subtle behavior because the resulting sequence can be mutated by the object:

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]

I would think that this is quite unexpected behavior (in a mostly functional language).

So, if the internal collection is mutable, you may also consider creating a complete clone of the data that cannot be modified later and guarantees that the returned sequence will always give the same results. For example using data |> Array.ofSeq |> Seq.readonly

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜