F# “的去糖化形式”;“让进来”;
x*x中的F# “的去糖化形式”;“让进来”;,f#,functional-programming,F#,Functional Programming,x*x中的让(x=0)转换成什么?函数(funx->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
让(x=0)转换成什么?函数(funx->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
绑定转换成函数了吗?普通的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 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
但是,让这些函数中的
绑定不会转换为函数本身。这两种代码转换为相同的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
的范围内作为常数进行评估,让x=in
在功能上等同于(fun x->)
是一个表达式
是一个值
中的关键字是可选的。您几乎可以看到让x=e1出现在e2
中,作为(fun x->e2)e1
的语法糖
在基本级别上,这两个表达式的意思是相同的-编译器可能会以不同的方式编译它们(取决于优化级别和它如何内联),但是您可以经常使用第二个符号,而不是第一个符号
它们不同的一种情况是,ML语言(包括F#)仅泛化使用let
关键字显式编写的函数类型。这意味着如果您使用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)
让2*2中的(a=2)翻译成(有趣的a->a*a)2
,或者有什么不同吗?谢谢我不禁想知道,如果变量a
不是常数呢?但是对函数的调用:let a=getNumberFromFile(),in…
-然后它会被转换(或等效)为:let fx=(fun a->x+2)(getNumberFromFile())
?(b
仍然是一个常量)。是的,它将编译为相同的CIL代码,但它不会在CIL级别为a
创建新函数。明白了。因此,我的问题中的result1
、result2
和result3
将编译为相同的代码,但不会为每个嵌套的let绑定创建新函数-相反,每个let绑定的表达式要么是常量(因此在编译时解析其值),要么是调用函数的函数(call
,callvirt
)并将值分配给let绑定-当然,这仅在CIL级别。@eb几乎没有。不带参数的let
绑定(let A=…
)编译为一个常量或一个取表达式值的局部变量(例如函数的返回值).Alet
与参数绑定(let f x=…
)可能会编译为函数,如果编译器无法将其更多地内联(请注意,在上述所有示例中,f5
编译为常量8
)。从功能等效的角度讲,您的意思是它们做的相同,但不一定编译为相同的代码(就像@p.s.w.g在他的回答中提到的那样?@ebb我相信在的情况下,让(fun x->)
在概念上存在,但是内联的。如果你明确使用(fun x->)
version,您正在显式地创建一个函数。因此编译器当然不需要内联它。因此,尽管它们在功能上是等效的,let
版本似乎至少应该与fun
版本一样高效。我现在没有访问编译代码视图的权限来验证。@eb是否在
关键字中包含,不会改变编译后的代码。这只是您希望源代码外观的一个选择。