3

私は現在、F# と一般的な関数型プログラミングを独学で学ぼうとしている趣味のプログラマー (本業は料理人) です。

とにかく、私は浮気をしDeflateStreamて、次の2つの関数を書きました:

let Compress compressMe =
    let ds = new DeflateStream(File.Create("compressed.txt"), CompressionMode.Compress)
    File.OpenRead(compressMe).CopyTo(ds)
    ds.Close()

let Decompress =
    let ds = new DeflateStream(File.OpenRead("compressed.txt"), CompressionMode.Decompress)
    ds.CopyTo(File.Create("decompressed.txt"))
    ds.Close()

メイン関数の本体では、次のように次々と呼び出されます。

Compress args.[0]
Decompress

ただし、プログラムの実行時に compress.txt が存在しない場合、 がDecompressスローされるのFileNotFoundExceptionは驚くべきことです。なぜなら、これをスローできるのは への呼び出しだけだからFile.OpenRead("compress.txt")です。約1時間後、メイン関数でそれを呼び出す前に、それDecompressが実装され、実行されていることがわかりました。IComparable定義を変更する と、let Decompress () = [...]実装されなくなりIComparable、意図したとおりにコードが実行されることがわかりました。なぜ F# がIComparable推論していたのか、なぜそのような推論によって関数が でマークされたメイン関数の前に実行されるのか教えてもらえます[<EntryPoint>]か? また、私のコードの命令的なスタイルを許してください。私はこれに非常に慣れていません。

事前に感謝します。

4

3 に答える 3

4

みたいなことを書くと

let value = 
    //some long calculation
[<Entrypoint>]
let main args = ...

コンパイラは の前に長い計算を実行しmainます。これは、おそらくコードの後半で値を使用するためです。あなたが見つけたように、これを抑制するには、を使用する必要がありますlet value() = ...

どこから来ているのかはわかりませんIcomparableが、これが何が起こっているかの鍵です。

書く場合は注意

let a = ...
let b = ...

コンパイラは、実行a前に計算されることを保証bします。

于 2012-04-29T04:20:09.617 に答える
4

IComparable ビットについては完全にはわかりませんが、問題は、括弧がないと、コンパイラがfunctionではなくDecompressとして扱っていることです。これは、あなたが書いた場合と同様です。

let compressedName = "compressed.txt"

その場合、compressedName値になりました。かっこを追加することで、これが、記述したコードによって (エントリ ポイントの前に) 一度初期化された値ではなく、関数が呼び出されるたびにコードを呼び出す必要がある関数であることをコンパイラに伝えます。

于 2012-04-29T03:44:52.980 に答える
0

他の人が指摘したように、宣言に括弧がないことは重要です。

let Decompres = ...

型の変数を宣言しますunit。この型は "データ" を表すために使用され (このデータが多くの情報をエンコードしない場合でも)、他のデータ指向型と同様に IComparable を実装します。

let Decompress() = ...

は関数を宣言し、F# の関数は比較できません。これはおそらく、関数の等価性について普遍的に受け入れられている概念がないためです。

Decompressの「IComparable-ness」が、あなたが得た例外と関係があることはわかりません。

于 2012-05-02T15:12:56.580 に答える