3

我是一名业余程序员(职业厨师),目前正在尝试自学 F# 和一般的函数式编程。

无论如何,我在鬼混DeflateStream,写了以下两个函数:

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()

在 main 函数的主体中,它们被一个接一个地调用,如下所示:

Compress args.[0]
Decompress

但是,如果在程序运行时compressed.txt 不存在,则会Decompress抛出 a FileNotFoundException,这令人惊讶,因为唯一可以抛出这个的是对File.OpenRead("compress.txt"). 大约一个小时后,我发现它Decompress正在实现IComparable并且在主函数中调用它之前正在执行。我发现通过将其定义更改为 let Decompress () = [...]不再实现IComparable,并且我的代码按预期执行。谁能告诉我为什么 F# 进行推断IComparable以及为什么这样的推断会导致函数在标有 的主函数之前执行[<EntryPoint>]?另外,请原谅我的代码的命令风格,我对此非常陌生。

提前致谢。

4

3 回答 3

4

我不完全确定 IComparable 位,但是您遇到的问题是,如果没有括号,编译器会将Decompress其视为value而不是function。这将类似于如果你写了。

let compressedName = "compressed.txt"

在这种情况下,compressedName现在是一个值。添加括号告诉编译器这是一个函数,每次调用该函数时都必须调用其代码,而不是由您编写的代码初始化一次(在入口点之前)的值。

于 2012-04-29T03:44:52.980 回答
4

当你写类似的东西时

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

编译器在之前执行长计算main。这是因为您稍后可能会在代码中使用该值。如您所见,要抑制这种情况,您需要使用let value() = ....

我不确定Icomparable来自哪里,但这是正在发生的事情的关键。

Note, if you write

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

The compiler will gurantee a is calculated before b executes.

于 2012-04-29T04:20:09.617 回答
0

As others have pointed out, the absence of parentheses in the declaration is significant.

let Decompres = ...

declares a variable of type unit. This type is used to represent "data" (even if this data doesn't encode much information), and it implements IComparable like any other data-oriented type.

let Decompress() = ...

declares a function, and functions in F# are not comparable, probably because there is no universally accepted notion of equality on functions.

I can't see that the "IComparable-ness" of Decompress had anything to do with the exception you got.

于 2012-05-02T15:12:56.580 回答