Collections 用序列包装可变集合

Collections 用序列包装可变集合,collections,f#,ienumerable,Collections,F#,Ienumerable,有时,我想从函数返回一个可变集合作为序列。向上转换到seq是可行的,但是序列可以向下转换和修改(这通常并不重要)。我通常的解决方案是使用wrap-as-a-sequence函数,该函数产生以下结果: let wrap items = Seq.map id let wrapDict dict = Seq.map ((|KeyValue|) >> snd) 主要是出于好奇(和乐趣),还有什么其他的方法来编写这样的函数呢,也许是用更惯用、简洁或性能更好的方式?就是您要找的函数。我认为St

有时,我想从函数返回一个可变集合作为序列。向上转换到
seq
是可行的,但是序列可以向下转换和修改(这通常并不重要)。我通常的解决方案是使用wrap-as-a-sequence函数,该函数产生以下结果:

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

主要是出于好奇(和乐趣),还有什么其他的方法来编写这样的函数呢,也许是用更惯用、简洁或性能更好的方式?

就是您要找的函数。

我认为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]
类型Arr()=
让数据=[| 1..5 |]
成员x.ItemsSeq=Seq.readonly数据
成员x.Mutate()=数据[0]List.of seq)/[1;2;3;4;5]
a、 突变
printfn“%A”(s |>List.ofSeq)/[10;2;3;4;5]
我认为这是非常意外的行为(用一种功能性语言来说)


这样,如果内部集合是可变的,那么您也可以考虑创建一个完整的数据克隆,该数据在以后无法修改,并保证返回的序列将总是给出相同的结果。例如,使用

data |>Array.ofSeq |>Seq.readonly

为什么不在作为序列返回之前在
ReadOnlyCollection
中包装然后可变的集合,所以向下转换然后突变不再是一个选项?+1好的一点,我需要在生成字典排列的实现中使用这种方法,它使用了一个带有内部修改的单一阵列:是的,完美。我不知道为什么我以前从没见过。