Упаковка изменяемой коллекции с последовательностью - PullRequest
3 голосов
/ 07 июля 2011

Иногда я хочу вернуть изменяемую коллекцию из функции в виде последовательности. Обновление до seq<_> работает, но последовательность может быть уменьшена и изменена (не то, что это обычно имеет значение). Мое обычное решение состоит в том, чтобы использовать функцию wrap-as-a-sequence, которая привела к следующему:

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

Главным образом для любопытства (и шутки), каковы были бы другие способы написания таких функций, возможно, более идиоматическим, кратким или производительным способом?

Ответы [ 2 ]

5 голосов
/ 07 июля 2011

Seq.readonly - это функция, которую вы ищете.

2 голосов
/ 07 июля 2011

Я думаю, что функция, предложенная Стефаном, вероятно, то, что вы ищете.

Однако есть одна хитрая вещь - функция 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

...