2012-04-29 43 views
3

我是一个爱好者程序员(由贸易厨师),目前正试图自学F#和函数式编程。为什么F#推断我的函数实现了IComparable?

反正我是用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() 

在主函数体中,他们被称为一个接一个正确的是这样的:

Compress args.[0] 
Decompress 

但是,如果程序运行时不存在compressed.txt,则Decompress会抛出FileNotFoundException,这是令人惊讶的,因为唯一可能引发此问题的是致电File.OpenRead("compress.txt")。大约一个小时后,我发现Decompress正在执行IComparable,并且在主函数调用它之前正在执行。我发现通过将其定义更改为let Decompress() = [...],它不再执行IComparable,并且我的代码按照它的意图执行。任何人都可以告诉我为什么F#推断IComparable以及为什么这样的推理会导致函数在标记为[<EntryPoint>]的主函数之前执行?另外,请原谅我的代码的不完美风格,我对此非常感兴趣。

感谢adavance。

+2

顺便说一句,DeflateStream实现IDisposable,所以你应该使用“使用”的关键字,而不是“让”来创建它。这将确保当流超出范围时流正确处置(并关闭)。请参阅http://msdn.microsoft.com/en-us/library/dd233240(v=vs.110).aspx – Asik 2012-04-29 03:52:09

+0

谢谢,我会牢记这一点。 – 2012-04-29 04:14:13

+0

似乎很奇怪,它传染IComparable,因为表达式的类型是单位据我可以告诉(返回类型ds.Close我单位) – 2012-04-29 20:00:12

回答

4

我不能完全肯定了IComparable位,但你有问题,如果没有括号,编译器处理Decompress不是功能。这与您写下的内容类似。

let compressedName = "compressed.txt" 

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

+0

谢谢。我觉得这很简单。 – 2012-04-29 04:26:44

4

当你喜欢写东西

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

编译器main之前执行长的计算。这是因为你可能以后在你的代码中使用这个值。为了压制这一点,如你所见,你需要使用let value() = ...

我不确定Icomparable是从哪里来的,但这是发生什么事的关键。

注意,如果你写

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

编译器会出示担保a之前b执行计算。

0

正如其他人所指出的那样,声明中括号的缺失是很重要的。

let Decompres = ... 

声明类型为unit的变量。这种类型用于表示“数据”(即使这些数据不会编码太多的信息),并且像其他任何面向数据的类型一样实现IComparable。

let Decompress() = ... 

声明的函数,并在F#的功能是不可比的,可能是因为有功能上的平等,没有普遍接受的概念。

我看不到的Decompress的“IComparable的性”有任何与你有例外。

相关问题