0

我试图弄清楚如何从 F# 中的单个函数管理多个惰性序列。

例如,在下面的代码中,我试图获取两个序列 - 一个返回目录中的所有文件,另一个返回无法访问(例如由于权限)的任何目录的元组序列例外。

当下面的代码编译并运行时,errorSeq 在被其他代码使用时从来没有任何元素,即使我知道发生了 UnauthorizedAccess 异常。

我正在使用 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
4

2 回答 2

3

如果您想采用更实用的方法,这里有一种方法:

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

现在我们每次将错误序列和文件序列传递给函数,并返回通过在函数中附加到它们而创建的新序列。不过,我认为在这种情况下,命令式方法更容易遵循。

于 2010-10-28T14:13:24.713 回答
2

Seq.append返回一个新序列,所以这个

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

没有效果。也许您希望您的函数返回两个序列的元组?或者在遇到错误时使用某种可变集合来编写错误?

于 2010-10-28T06:23:11.247 回答