F#中的函数。。为什么它没有编译
我已经编写了两个版本的代码。第一个按预期工作并打印“Hi”。第二个给了我一个错误“这个let后面的块未完成” 第一版F#中的函数。。为什么它没有编译,f#,F#,我已经编写了两个版本的代码。第一个按预期工作并打印“Hi”。第二个给了我一个错误“这个let后面的块未完成” 第一版 #light let samplefn() = let z = 2 let z = z * 2 printfn "hi" samplefn() 第二版 #light let samplefn() = let z = 2 let z = z * 2
#light
let samplefn() =
let z = 2
let z = z * 2
printfn "hi"
samplefn()
第二版
#light
let samplefn() =
let z = 2
let z = z * 2
samplefn()
唯一的区别是第二版中没有printfn。我正在使用VisualStudio2010作为我的IDE。我对F#很陌生,但这个错误对我来说似乎很奇怪。我想我遗漏了一些非常重要的概念。请解释一下
编辑:如果我在函数外执行此操作,即使是在代码的第一个版本中,也会出现错误
#light
let z = 2
let z = z * 2
printfn "Error: Duplicate definition of value z"
不在顶层的
let
必须在赋值后有一个称为“body”的语句(实际上是一个表达式,如pst所述)。在第一个示例中,主体是printfn“hi”
,而第二个示例没有主体。这就是编译器所抱怨的
请注意,在函数定义中,内部让表达式实际创建嵌套作用域。也就是说,let z=z*2
实际上创建了一个名为z
的新值,并将外部z
乘以2的值绑定到它,然后在let
的主体中使用它(在本例中是printfn
)。嵌套的let
将始终具有主体。嵌套允许看似重复的定义
由于最外层的let
不需要主体,编译器认为您试图在同一范围内重新定义z
,这是一个错误。可以使用括号告诉编译器如何正确解释最后一个示例:
let z = 2
(let z = z * 2
printfn "z = %d" z)
printfn "z = %d" z
上面将打印z=4
z = 4
z = 2
z=2让
将一个值绑定到标签上,但除此之外,没有其他作用。您的函数包含两个绑定,但未使用它们,因此会出现错误
换句话说,F#中的所有函数都需要一个返回值,即函数中最后执行的表达式的值let
没有返回值,因此函数无效。要解决此问题,可以添加返回值,例如:
let samplefn() =
let z = 2
let z = z * 2
()
它定义了一个完全不执行任何操作的函数(返回unit
)。也许更好的例子是:
let samplefn() =
let z = 2
let z = z * 2
z
它将返回4(标签z
的绑定值)。我认为理解这里的非light语法很有帮助。让我们翻译一下:
第1版(let绑定表达式)
这里需要了解的重要一点是,所有非顶级let绑定实际上都是let=in
形式的表达式,其中
绑定到新范围
中的
结果,并且
是整个表达式的返回值。light语法让您相信这样的let绑定是变量赋值/语句,而事实上F#中几乎所有内容都是表达式
也许以下内容更清楚地说明了这一点:
let a = (let b = 3 in b + 2) //a is 5
第二版(顶级let绑定)
顶级let绑定以;;终止代码>,表示可能被认为是语句的完成。顶层是一个单一的作用域,这里我们得到一个错误,因为我们试图在同一个作用域内绑定两次z
。而在示例1中使用let绑定的表达式形式,我们为表达式链中的每个子作用域重新绑定z
。请注意,我们可以在顶层执行以下操作:
let z = (let z = 2 in z * 2);;
谢谢我已编辑了我的问题,使其具有另一个条件。你能解释一下吗?“经过一段时间后,你必须有一个表达”——我想这并不总是正确的。因为我可以只编译#light let x=42,所以我编辑了我的答案以解释您的编辑。
let z = 2;;
let z = z * 2;;
printfn "Error: Duplicate definition of value z";;
let z = (let z = 2 in z * 2);;