私はグーグルで読んで、それを行うための「正しい」方法を見つけようとしていますが、SOで読んだすべての質問は完全に異なる答えを持っているようです。
これが私の問題の要点です。ファイルには、トリプル(a:string、b:string、c:Int64)のseqの型アノテーションがあります。f#に慣れていないので、型アノテーションの表現にまだ精通していません(または、さらに言えば、型シグネチャを理解することもできません)。aはファイル名、bは内部識別子、cはファイルの長さ(サイズ)を表す値です。baseconfigは、コードの前半の文字列です。
ignore(files
|> Seq.filter( fun(x,y,z) -> y = baseconfig) // used to filter only files we want
|> Seq.fold( fun f n ->
if( (fun (_,_,z) -> z) n > 50L*1024L*1024L) then
zipfilex.Add((fun (z:string, _, _) -> z) n)
printfn("Adding 50mb to zip")
zipfilex.CommitUpdate()
zipfilex.BeginUpdate()
("","",0L)
else
zipfilex.Add((fun (z, _, _) -> z) n)
("", "", (fun (_, _, z:Int64) -> z) n + (fun (_, _, z:Int64) -> z) f)
) ("","",0L)
)
このコードのチャンクが行うことになっているのは、の各ファイルを反復処理しfiles
、それをzipアーカイブに追加することです(実際には、後でコミットするためにリストに追加されます)。ファイルが50 MBを超えると、現在のファイルをコミットします。 zipアーカイブへの保留中のファイル。ファイルの追加は安価で、コミットは高価なので、バッチ処理することでコストを軽減しようとしています。
これまでのところ、コードはちょっと機能します...コミットされたファイルの150MBに近づいたときに取得したObjectDisposedExceptionを除いて。しかし、これがそのような操作を行う正しい方法であるかどうかはわかりません。型破りな使い方をしているような気がしSeq.fold
ますが、それでももっといい方法がわかりません。
ボーナスの質問:タプルから値をスナイプするためのより良い方法はありますか?fstとsndは2つの値のタプルに対してのみ機能し、私が行ったようにインライン化する代わりに独自の関数を定義できることを認識していますが、より良い方法があるはずです。
更新:以前のフォールドの試みでは、なぜInt64をアキュムレータとして使用できないのか理解できませんでした。重要な括弧が欠けていたことがわかりました。以下の少し単純なバージョン。また、すべてのクレイジーなタプル抽出を排除します。
ignore(foundoldfiles
|> Seq.filter( fun (x,y,z) -> y = baseconfig)
|> Seq.fold( fun (a) (f,g,j) ->
zipfilex.Add( f)
if( a > 50L*1024L*1024L) then
printfn("Adding 50mb to zip")
zipfilex.CommitUpdate()
zipfilex.BeginUpdate()
0L
else
a + j
) 0L
)
更新2:命令型の解決策を採用する必要があります。F#は、後続のステートメントでzipファイルを閉じた後、どういうわけかこのコードブロックを再入力しています。これはObjectDisposedExceptionを説明しています。それがどのように機能するのか、またはその理由はわかりません。