我是一个业余爱好者程序员(通过贸易做饭),目前正在尝试自学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()
在主要功能的主体中,它们一个接一个地被称为:
Compress args.[0]
Decompress
但是,如果在运行程序时{(1}}}不存在,则Decompress
会抛出FileNotFoundException
,这是令人惊讶的,因为唯一可以抛出此内容的是调用File.OpenRead("compress.txt")
。大约一个小时后,我发现Decompress
正在实施IComparable
,并且在主函数调用它之前正在执行。我发现通过将其定义更改为let Decompress () = [...]
,它不再实现IComparable
并且我的代码按照预期执行。任何人都可以告诉我为什么F#推断IComparable
以及为什么这样和推断会导致函数在标有[<EntryPoint>]
的主函数之前执行?另外,请原谅我的代码的不完美风格,我在这方面非常新。
谢谢你。
答案 0 :(得分:4)
我不完全确定IComparable位,但问题是如果没有括号,编译器会将Decompress
视为值而不是函数。这与你写过的内容类似。
let compressedName = "compressed.txt"
在这种情况下,compressedName
现在是一个值。添加括号告诉编译器这是一个函数,每次函数时都必须调用它的代码,而不是由你编写的代码初始化一次(在入口点之前)的值。
答案 1 :(得分:4)
当你写
之类的东西时let value =
//some long calculation
[<Entrypoint>]
let main args = ...
编译器在main
之前执行长计算。这是因为您可能稍后在代码中使用该值。要取消此操作,您需要使用let value() = ...
。
我不确定Icomparable
的来源,但这是发生事情的关键。
注意,如果你写
let a = ...
let b = ...
编译器将在a
执行之前计算保证b
。
答案 2 :(得分:0)
正如其他人所指出的那样,声明中没有括号是很重要的。
let Decompres = ...
声明类型为unit
的变量。此类型用于表示“数据”(即使此数据不编码很多信息),它实现IComparable,就像任何其他面向数据的类型一样。
let Decompress() = ...
声明一个函数,并且F#中的函数不具有可比性,可能是因为函数上没有普遍接受的相等概念。
我看不出Decompress
的“IC Comparable-ness”与您获得的例外情况有关。