F# “的去糖化形式”;“让进来”;

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*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

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=…
)编译为一个常量或一个取表达式值的局部变量(例如函数的返回值).A
let
与参数绑定(
let f x=…
)可能会编译为函数,如果编译器无法将其更多地内联(请注意,在上述所有示例中,
f5
编译为常量
8
)。从功能等效的角度讲,您的意思是它们做的相同,但不一定编译为相同的代码(就像@p.s.w.g在他的回答中提到的那样?@ebb我相信在
的情况下,让
(fun x->)
在概念上存在,但是内联的。如果你明确使用
(fun x->)
version,您正在显式地创建一个函数。因此编译器当然不需要内联它。因此,尽管它们在功能上是等效的,
let
版本似乎至少应该与
fun
版本一样高效。我现在没有访问编译代码视图的权限来验证。@eb是否在
关键字中包含
,不会改变编译后的代码。这只是您希望源代码外观的一个选择。