Есть ли более общий способ итерации, фильтрации, применения операций к коллекциям в F #? - PullRequest
1 голос
/ 02 октября 2011

Давайте возьмем этот код:

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.

Я делаю это неправильно?

Ответы [ 3 ]

5 голосов
/ 02 октября 2011

В зависимости от вашей ситуации вам может понадобиться или нет необходимость отслеживать, с каким типом коллекций вы имеете дело.

В случае простой перебора элементов ничто не может помешать вам использовать Seq.iter в спискахили массивы в F #: он будет работать как с массивами, так и со списками, поскольку оба они также являются последовательностями или IEnumerable s с точки зрения .NET.Использование Array.iter над массивом или List.iter над списком просто предложит более эффективные реализации обхода, основанные на конкретных свойствах каждого типа коллекции.Как показывает сигнатура Seq.iter Seq.iter : ('T -> unit) -> seq<'T> -> unit, вам не важен ваш тип 'T после обхода.

В других ситуациях вы можете рассмотреть типы входных и выходных аргументов и использовать специализированные функции,если вы заботитесь о дальнейшей композиции.Например, если вам нужно отфильтровать список и продолжить использовать результат, то

List.filter : ('T -> bool) -> 'T list -> 'T list сохранит вам тип базовой коллекции без изменений, но применение Seq.filter : ('T -> bool) -> seq<'T> -> seq<'T> к списку вернет вам последовательность,больше нет списка:

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
4 голосов
/ 02 октября 2011

Seq.iter также работает со списками и массивами.

Тип seq на самом деле является псевдонимом для интерфейса IEnumerable<'T>, который реализуют list и array.Таким образом, как указано в BLUEPIXY, вы можете использовать Seq.* функции для массивов или списков.

Менее функциональным выглядит следующее:

for x in [1..10] do
    printfn "%A" x
2 голосов
/ 02 октября 2011

List и Array обрабатываются как Seq.

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

printAll lines
printAll [1..10]
printAll [|1..10|]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...