2011-07-07 3 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

관련 문제