F# (Mis)理解Seq.cache
我有以下代码(在一个更大的函数中,但这不重要):F# (Mis)理解Seq.cache,f#,sequence,F#,Sequence,我有以下代码(在一个更大的函数中,但这不重要): let ordersForTask=Dictionary() 让getOrdersForTask任务= 将ordersForTask.TryGetValue任务与 |正确,订单->订单 |错误,-> 发号施令= 场景。订单 |>Seq.filter(fun(order:order)->order.Tasks.Contains(task)) |>Seq.cache ordersForTask.Add(任务、订单) 命令 据我所知,这应该会导致对每
let ordersForTask=Dictionary()
让getOrdersForTask任务=
将ordersForTask.TryGetValue任务与
|正确,订单->订单
|错误,->
发号施令=
场景。订单
|>Seq.filter(fun(order:order)->order.Tasks.Contains(task))
|>Seq.cache
ordersForTask.Add(任务、订单)
命令
据我所知,这应该会导致对每对order
和task
值调用order.Tasks.Contains()
一次,无论使用相同的task
值调用getOrdersForTask
的频率有多高,因为输入序列只迭代(最多)一次。然而,情况似乎并非如此;如果我为我拥有的task
的所有值调用函数n
次,则分析显示n*订单数量*任务数量
调用Contains()
用Seq.toList
替换Seq.cache
具有我预期的效果,但我希望避免产生Seq.toList
的成本
我对
Seq.cache
有什么误解,或者它的用法有什么错误?看起来每次调用函数时,函数都会返回一个新的缓存序列。也许这对你会有帮助:task
是上游C#code中某个地方定义的一个普通CLR类。为了确保我用task=int
,orders=int-seq
和一个简单的过滤函数(n->n%5==0
)尝试了你的构造(包括查看调用的跟踪消息)-在F#interactive中,它可以正常工作(意思是:过滤函数只有在我第一次使用某个数字求值时才会被调用)-您能否尝试给出一个最小的示例来说明您的问题,这样我们就可以看到一个失败的版本?仅供参考;这可能有助于研究(第1385行)。请注意,使用Seq.cache也有成本(最显著的是锁)。有时候Seq.toArray可能更有效。下面是一个独立的复制尝试,与@CarstenKönig的评论类似。很好。我们需要完整的示例代码。
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