开发者

Wrapping a mutable collection with a sequence

开发者 https://www.devze.com 2023-03-18 01:48 出处:网络
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开发者

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

精彩评论

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