F#序列中的Guid生成

时间:2015-05-05 14:57:45

标签: f#

我有以下代码:

open System
open System.Linq

type Child = {
    id: Guid
    name: int
    parent: Guid
}

type Parent = {
    id: Guid
    name: int
    children: seq<Guid>
}

let makeChild name parentId =
    {
        Child.id = Guid.NewGuid()
        name = name
        parent = parentId
    }

let makeParent (group: IGrouping<int, int>) =
    let id = Guid.NewGuid()
    let children = group |> Seq.map (fun x -> makeChild x id)
    let ids = children |> Seq.map (fun x -> x.id)
    ({
        Parent.id = id
        name = group.Key
        children = ids
    }, children)

let makeAll (groups: seq<IGrouping<int, int>>) =
    let result = groups |> Seq.map (fun x -> makeParent x)
    let children = result |> Seq.map (fun x -> snd x) |> Seq.concat
    let parents = result |> Seq.map (fun x -> fst x)
    (parents, children)

(我接受IGrouping<int, int>而不是seq<int * seq<int>>,因为此代码需要与C#互操作。)

但是,当我使用以下内容运行时:

let parents, children = makeAll(Enumerable.Range(0, 100).GroupBy(fun x -> x % 10))

然后没有孩子。[i] .parent guids与父母相关。[j] .children。[k] guids for i,j,k。

为什么不是这样?我怎么能这样做呢?

1 个答案:

答案 0 :(得分:3)

没有对此进行测试,但似乎问题在于您将结果seq两次枚举,一次在let children,一次在let parents行。由于guid生成具有副作用,因此每个枚举都会得到两个不同的结果。

如果您在let result行缓存seq(或通过将其转换为数组或同一行中的列表来实现它),您应该得到您正在寻找的内容:

let result = groups |> Seq.map (fun x -> makeParent x) |> Seq.cache

makeParent函数中的相同内容。 ids seq也需要缓存。

&#34;陷阱&#34;这就是为什么我发现最好在函数或接口的边界上使用具体的集合类型而不是seqs。如果您正在寻找懒惰,可以使用Lazy类型使其明确。