0

F# で単一の関数から複数の遅延シーケンスを管理する方法を理解しようとしています。

たとえば、以下のコードでは、2 つのシーケンスを取得しようとしています。1 つはディレクトリ内のすべてのファイルを返し、もう 1 つはアクセスできなかったディレクトリのタプルのシーケンスを返します (たとえば、パーミッションが原因で)例外。

UnauthorizedAccess 例外が発生したことはわかっていますが、以下のコードはコンパイルして実行されますが、他のコードで使用される場合、errorSeq には要素がありません。

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 
[||] 

効果はありません。おそらく、関数が 2 つのシーケンスのタプルを返すようにしたいですか? または、ある種の可変コレクションを使用して、エラーが発生したときにエラーを書き込みますか?

于 2010-10-28T06:23:11.247 に答える