我写了两个版本的代码.第一个按预期工作并打印"嗨".第二个给我一个错误,"阻止这个让未完成"
第一版
#light
let samplefn() =
let z = 2
let z = z * 2
printfn "hi"
samplefn()
Run Code Online (Sandbox Code Playgroud)
第二版
#light
let samplefn() =
let z = 2
let z = z * 2
samplefn()
Run Code Online (Sandbox Code Playgroud)
唯一的区别是第二版中没有printfn.我使用Visual Studio 2010作为我的IDE.我对F#很新,但这个错误对我来说似乎很奇怪.我想我错过了一些非常重要的概念.请解释.
编辑:此外,如果我在函数外执行此操作,即使使用第一个版本的代码,我也会收到错误.
#light
let z = 2
let z = z * 2
printfn "Error: Duplicate definition of value z"
Run Code Online (Sandbox Code Playgroud)
let将值绑定到标签,否则不会执行其他操作.您的函数包含两个绑定但不使用它们,因此您会收到错误.
换句话说,F#中的所有函数都需要一个返回值,它是函数中最后执行的表达式的值. let没有返回值,因此您的函数无效.要解决此问题,您可以添加返回值,例如:
let samplefn() =
let z = 2
let z = z * 2
()
Run Code Online (Sandbox Code Playgroud)
它定义了一个绝对不做任何事情的函数(返回unit).也许更好的例子是:
let samplefn() =
let z = 2
let z = z * 2
z
Run Code Online (Sandbox Code Playgroud)
它将返回4(标签的绑定值z).
我认为这里理解非轻量语法很有帮助.让我们翻译:
let samplefn() =
let z = 2 in
let z = z * 2 in
printfn "hi";;
samplefn();;
Run Code Online (Sandbox Code Playgroud)
这里要理解的重要一点是,所有非顶级let绑定实际上是表单的表达式let <variable> = <expression1> in <expression2>,<variable>它绑定到<expression1>新作用域的结果<expression2>,并且<expression2>是整个表达式的返回值.轻量级语法让你相信这样的绑定是变量赋值/语句,而实际上F#中的几乎所有东西都是表达式.
也许下面更清楚地说明了这一点:
let a = (let b = 3 in b + 2) //a is 5
Run Code Online (Sandbox Code Playgroud)
let z = 2;;
let z = z * 2;;
printfn "Error: Duplicate definition of value z";;
Run Code Online (Sandbox Code Playgroud)
顶级let-bindings终止;;,表示可以将其视为语句的完成.顶级是一个范围,在这里我们得到一个错误,试图z在同一范围内绑定两次.使用示例1中的let绑定的表达形式,我们z为表达链中的每个子范围重新绑定.请注意,我们可以在顶层执行类似的操作:
let z = (let z = 2 in z * 2);;
Run Code Online (Sandbox Code Playgroud)