开发者

Is there a more generic way of iterating,filtering, applying operations on collections in F#?

开发者 https://www.devze.com 2023-04-10 16:46 出处:网络
Let\'s take this code: open System open System.IO let lines = seq { use sr = new StreamReader(@\"d:\\a.h\")

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 f开发者_高级运维act that I am using a List, an Array, or a Seq.

Am I doing it wrong?


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, or IEnumerables from .NET standpoint. Using Array.iter over an array, or List.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.iter Seq.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, but Seq.filter : ('T -> bool) -> seq<'T> -> seq<'T> being applied to a list will return you a sequence, not a list anymore:

let alist = [1;2;3;4] |> List.filter (fun x -> x%2 = 0) // alist is still a list
let aseq = [1;2;3;4] |> Seq.filter (fun x -> x%2 = 0) // aseq is not a list anymore


Seq.iter works on lists and arrays just as well.

The type seq is actually an alias for the interface IEnumerable<'T>, which list and array both implement. So, as BLUEPIXY indicated, you can use Seq.* functions on arrays or lists.

A less functional-looking way would be the following:

for x in [1..10] do
    printfn "%A" x


List and Array is treated as Seq.

let printAll seqData =
  seqData |> Seq.iter (printfn "%A")
  Console.ReadLine() |> ignore

printAll lines
printAll [1..10]
printAll [|1..10|]
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号