为何F#中以下代码会延迟计算quotes且执行两次?
为什么你的F#代码中
quotes被延迟计算了两次? 这其实是F#里序列(Seq)的惰性求值特性在搞鬼,很多刚接触F#的开发者都会踩这个坑!
先给你拆解核心原因:
- 你的
getFundsClosingPrice dbFunds返回的应该是seq<'T>类型的序列。F#的序列是惰性的——它不会在你把结果赋值给quotes的时候就立刻执行HTTP请求获取数据,而是每次你遍历这个序列时,才会重新执行底层的数据源逻辑(也就是你的HTTP GET请求)。 - 看你代码里的两处使用场景:
- 第一次用
quotes |> Seq.maxBy ...时,程序需要遍历整个序列找到最大的TradedOn,这时候才真正触发getFundsClosingPrice执行,拉取第一份数据; - 第二次用
quotes |> Seq.map ...时,又要遍历一次序列生成新的集合,所以getFundsClosingPrice被再次调用,导致两次HTTP请求。
- 第一次用
怎么解决这个问题?
有两种常用方案,你可以根据数据量和场景选择:
转换成急切求值的集合(List/Array)
如果数据量不大,直接把序列转成List或者Array,这样赋值时就会立刻执行请求,把数据加载到内存里,后续所有操作都是基于内存中的静态集合,不会重复请求:let quotes = getFundsClosingPrice dbFunds |> List.ofSeq // 也可以用 Array.ofSeq用
Seq.cache()缓存序列结果
如果数据量较大,不想一次性加载到内存,可以用Seq.cache()缓存第一次遍历的结果,后续再使用这个序列时,会直接调用缓存的数据,不会重新执行求值逻辑:let quotes = getFundsClosingPrice dbFunds |> Seq.cache
简单总结:F#序列默认是“用到才计算”,如果需要复用计算结果,必须显式告诉程序把结果存下来~
内容的提问来源于stack exchange,提问作者Mario
相关产品推荐
相关产品推荐

