F # Управление несколькими ленивыми последовательностями из одного метода? - PullRequest
0 голосов
/ 28 октября 2010

Я пытаюсь выяснить, как управлять несколькими ленивыми последовательностями из одной функции в F #.

Например, в приведенном ниже коде я пытаюсь получить две последовательности - одну, которая возвращает все файлы в каталогах, и другую, которая возвращает последовательность кортежей любых каталогов, к которым нет доступа (например,из-за разрешений) за исключением.

Хотя приведенный ниже код компилируется и запускается, errorSeq никогда не имеет никаких элементов при использовании другим кодом, хотя я знаю, что возникли исключения UnauthorizedAccess.

IЯ использую F # 2.0.

#light
open System.IO
open System

let rec allFiles errorSeq dir = 
    Seq.append
        (try 
            dir |> Directory.GetFiles
         with
            e -> Seq.append errorSeq [|(dir, e)|]
                 |> ignore
                 [||]
        )
        (try
            dir 
            |> Directory.GetDirectories 
            |> Seq.map (allFiles errorSeq)
            |> Seq.concat
         with
            e -> Seq.append errorSeq [|(dir, e)|]
                 |> ignore
                 Seq.empty
        )

[<EntryPoint>]
let main args =
    printfn "Arguments passed to function : %A" args
    let errorSeq = Seq.empty
    allFiles errorSeq args.[0] 
    |> Seq.filter (fun x -> (Path.GetExtension x).ToLowerInvariant() = ".jpg")
    |> Seq.iter Console.WriteLine
    errorSeq
    |> Seq.iter (fun x -> 
                     Console.WriteLine("Error") 
                     x)
    0

Ответы [ 2 ]

3 голосов
/ 28 октября 2010

Если вы хотите использовать более функциональный подход, вот один из способов сделать это:

let rec allFiles (errorSeq, fileSeq) dir  = 
  let files, errs =
    try 
      Seq.append (dir |> Directory.GetFiles) fileSeq, errorSeq
    with 
      e -> fileSeq, Seq.append [dir,e] errorSeq 
  let subdirs, errs =
    try
      dir |> Directory.GetDirectories, errs
    with
      e -> [||], Seq.append [dir,e] errs
  Seq.fold allFiles (errs, files) subdirs

Теперь мы каждый раз передаем последовательность ошибок и последовательность файлов в функцию и возвращаем новые последовательности, созданные путем добавления к ним внутри функции. Я думаю, что императивный подход немного легче следовать в этом случае.

2 голосов
/ 28 октября 2010

Seq.append возвращает новую последовательность, поэтому это

Seq.append errorSeq [|(dir, e)|] 
|> ignore 
[||] 

не имеет никакого эффекта.Возможно, вы хотите, чтобы ваша функция возвращала кортеж из двух последовательностей?Или использовать какую-то изменчивую коллекцию для записи ошибок по мере их появления?

...