我正在fsharpforfunandprofit网站上阅读Choosing between collection functions,他展示了一个例子,说明在处理完资源后如何避免访问一次性资源(第28条,就在文章的最后)。
他使用以下内容模拟了一个数据库......
let dbConnection() =
printfn "Opening connection"
{ new System.IDisposable with
member this.Dispose() =
printfn "Disposing connection"
}
// Read some records from the database
let readCustomersFromDb conn n =
let makeCustomer i =
sprintf "Customer %d" i
seq {
for i = 1 to n do
let customer = makeCustomer i
printfn "Loading %s from the database" customer
yield customer
}
...然后展示了如何通过在返回序列之前枚举序列来避免这个问题......
let readCustomers() =
use conn = dbConnection()
let results = readCustomersFromDb conn 2
results |> List.ofSeq
我对最后一点感到有点困惑,因为我认为我们有一个序列,并希望将其转换为列表。这就是它在C#中的工作方式,这可能是我错误思考的地方。他似乎正在列出一个列表并将其转换为序列。
无论如何,我尝试将最后一行改为......
results |> Seq.toList
......它的工作原理相同。
那么,两者之间有什么区别,为什么他们在这里做同样的事情呢?我认为序列是非枚举的,在这种情况下我会期望他的原始代码不起作用。
答案 0 :(得分:10)
List.ofSeq
和Seq.toList
都有'a seq -> 'a list
类型,List.ofSeq
确实定义为
let ofSeq source = Seq.toList source
(在Microsoft.FSharp.Collections.List
module中定义)
所以他们确实是一样的。
当你得到一个列表(与seq
不同 - 是F#中的严格结构)时,将评估序列的所有元素以填充内存中的列表 - 这就是为什么你可以使用这两个函数都强制迭代所有值。