let (x = 0) in x * x
转化为什么?函数(fun x -> x * x) 0)
? - 这是有道理的,因为let
绑定是表达式 - 而表达式必须返回值(就像函数一样)。
示例:
let result1 =
(fun n1 -> (fun n2 ->
(fun n3 -> n1 + n2 + n3 ) 3) 2) 1
let result2 =
let n1 = 1 in
let n2 = 2 in
let n3 = 3 in
n1 + n2 + n3
let result3 =
let n1 = 1
let n2 = 2
let n3 = 3
n1 + n2 + n3
我是否正确地认为result3
是result2
的加糖形式,result2
是result1
的加糖形式?
简短:let in
绑定是否转换为函数?
答案 0 :(得分:11)
您几乎可以将let x = e1 in e2
视为(fun x -> e2) e1
的语法糖。
在基本级别,这两个表达式意味着相同的事情 - 编译器可能会以不同的方式编译它们(取决于优化级别以及它如何内联),但是您可以经常使用第二种表示法而不是第一种表示法。 / p>
它们不同的一种情况是ML语言(包括F#)仅使用let
关键字明确编写的 generalize 函数类型。这意味着如果您使用fun
,则该语言不会将其视为通用函数。如果你想要一个泛型函数,你必须使用let
(这不仅仅是一个编译器工件,这实际上是语言的一部分。)
例如,以下内容使用let
并且有效:
let id = (fun x -> x) in ignore(id 1); ignore(id "A")
但是以下方法不起作用,因为id
不是通用函数:
(fun id -> ignore(id 1); ignore(id "A")) (fun x -> x)
答案 1 :(得分:4)
普通的let
只是详细let … in
的轻量级语法形式。
嵌套
let
绑定:轻量级语法:
let f x = let a = 1 let b = 2 x + a + b
详细语法:
let f x = let a = 1 in let b = 2 in x + a + b
但是,这些函数中的let
绑定不会转换为函数本身。这两个转换为相同的CIL代码:
f:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ldc.i4.2
IL_0005: add
IL_0006: ret
请注意,此处唯一的功能是外部函数f
。变量a
和b
被评估为f
范围内的常量。
答案 2 :(得分:1)
let x = <val> in <expr>
在功能上等同于(fun x -> <expr>) <val>
。
<expr>
是一个表达式<val>
是一个值 in
关键字是可选的。