(错误)理解 Seq.cache

(Mis)understanding Seq.cache

提问人:TeaDrivenDev 提问时间:5/7/2015 更新时间:5/7/2015 访问量:1141

问:

我有以下代码(在一个更大的函数中,但这并不重要):

let ordersForTask = Dictionary<_, _>()

let getOrdersForTask task =
    match ordersForTask.TryGetValue task with
    | true, orders -> orders
    | false, _ ->
        let orders =
            scenario.Orders
            |> Seq.filter (fun (order : Order) -> order.Tasks.Contains(task))
            |> Seq.cache

        ordersForTask.Add(task, orders)
        orders

据我了解,这应该导致对每对 and 值只调用一次,无论使用相同值调用的频率如何,因为输入序列只迭代(最多)一次。然而,情况似乎并非如此。如果我为我拥有的所有值调用函数时间,则分析显示对 的调用。order.Tasks.Contains()ordertaskgetOrdersForTasktaskntaskn * number of orders * number of tasksContains()

替换为具有我预期的效果,但我想避免产生 的成本。Seq.cacheSeq.toListSeq.toList

我在使用它时误解了什么或做错了什么?Seq.cache

F# 序列

评论

0赞 PiotrWolkowski 5/7/2015
看起来您的函数每次调用函数时都会返回一个新的缓存序列。也许这会对你有所帮助:stackoverflow.com/a/1060594/3330348
0赞 TeaDrivenDev 5/7/2015
task属于在上游 C# 代码中某处定义的普通 CLR 类。
3赞 Random Dev 5/7/2015
只是为了确保我尝试了您的构造,以及一个简单的函数()用于过滤(包括用于查看调用的跟踪消息) - 好吧,在 F# 交互式中,它按应有的方式工作(意思是:过滤器函数只会在我第一次使用特定数字进行评估时调用) - 您能否尝试给出一个显示您的问题的最小示例, 所以我们可以有一个失败的版本来查看吗?Task = intorders = int seqn -> n % 5 == 0
3赞 Just another metaprogrammer 5/7/2015
仅供参考;研究 Seq.cache(第 1385 行)可能很有用。请注意,使用 Seq.cache 也是有成本的(最明显的是锁)。有时 Seq.toArray 可以更有效率。
2赞 latkin 5/8/2015
这是一个独立的重现尝试,与@CarstenKönig的评论一致。工作正常。我们将需要完整的示例代码。gist.github.com/latkin/1fa448d941c9383a4bc7

答: 暂无答案