在 F# 中是否有更通用的方法对集合进行迭代、过滤和应用操作?
让我们看一下这段代码:
open System
open System.IO
let lines = seq {
use sr = new StreamReader(@"d:\a.h")
while not sr.EndOfStream do yield sr.ReadLine()
}
lines |> Seq.iter Console.WriteLine
Console.ReadLine()
在这里,我正在读取 seq
中的所有行,并使用 Seq.iter
来检查它。如果我有一个列表,我将使用 List.iter
,如果我有一个数组,我将使用 Array.iter
。是否有一个更通用的遍历函数我可以使用,而不必跟踪我拥有的集合类型?例如,在 Scala 中,我只需调用 foreach
并且无论我使用的是 List、Array 还是 Seq,它都会起作用。
我做错了吗?
Let's take this code:
open System
open System.IO
let lines = seq {
use sr = new StreamReader(@"d:\a.h")
while not sr.EndOfStream do yield sr.ReadLine()
}
lines |> Seq.iter Console.WriteLine
Console.ReadLine()
Here I am reading all the lines in a seq
, and to go over it, I am using Seq.iter
. If I have a list I would be using List.iter
, and if I have an array I would be using Array.iter
. Isn't there a more generic traversal function I could use, instead of having to keep track of what kind of collection I have? For example, in Scala, I would just call a foreach
and it would work regardless of the fact that I am using a List, an Array, or a Seq.
Am I doing it wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可能需要也可能不需要跟踪您处理的集合类型,具体取决于您的情况。
在对项目进行简单迭代的情况下,没有什么可以阻止您在 F# 中的列表或数组上使用
Seq.iter
:它将在数组和列表上工作,因为两者也是序列,或从 .NET 的角度来看,IEnumerable。在数组上使用 Array.iter 或在列表上使用 List.iter 只会根据每种类型集合的特定属性提供更有效的遍历实现。作为Seq.iter的签名
Seq.iter : ('T -> unit) -> seq<'T> -> unit
表明您不关心遍历后的类型'T
。在其他情况下,如果您关心进一步的组合,您可能需要考虑输入和输出参数的类型并使用专门的函数。例如,如果您需要过滤列表并继续使用结果,则
List.filter : ('T -> bool) -> 'T 列表 -> 'T list
会完整保留底层集合的类型,但是Seq.filter : ('T -> bool) -> seq<'T> -> seq<'T>
应用于列表将返回一个序列,而不是列表:You may or may not need to keep track of what type of collection you deal with, depending on your situation.
In case of simple iterating over items nothing may prevent you from using
Seq.iter
on lists or arrays in F#: it will work over arrays as well as over lists as both are also sequences, orIEnumerable
s from .NET standpoint. UsingArray.iter
over an array, orList.iter
over a list would simply offer more effective implementations of traversal based on specific properties of each type of collection. As the signature of Seq.iterSeq.iter : ('T -> unit) -> seq<'T> -> unit
shows you do not care about your type'T
after the traversal.In other situations you may want to consider types of input and output arguments and use specialized functions, if you care about further composition. For example, if you need to filter a list and continue using result, then
List.filter : ('T -> bool) -> 'T list -> 'T list
will preserve you the type of underlying collection intact, butSeq.filter : ('T -> bool) -> seq<'T> -> seq<'T>
being applied to a list will return you a sequence, not a list anymore:Seq.iter
也适用于列表和数组。类型
seq
实际上是接口IEnumerable<'T>
的别名,list
和array
都实现了该接口。因此,正如 BLUEPIXY 所指出的,您可以在数组或列表上使用Seq.*
函数。一种看起来不太实用的方法如下:
Seq.iter
works on lists and arrays just as well.The type
seq
is actually an alias for the interfaceIEnumerable<'T>
, whichlist
andarray
both implement. So, as BLUEPIXY indicated, you can useSeq.*
functions on arrays or lists.A less functional-looking way would be the following:
List 和 Array 被视为 Seq。
List and Array is treated as Seq.