Desugared形式的“让步”

时间:2014-08-11 17:46:10

标签: f# functional-programming

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

我是否正确地认为result3result2的加糖形式,result2result1的加糖形式?

简短:let in绑定是否转换为函数?

3 个答案:

答案 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的轻量级语法形式。

来自MSDN: Verbose Syntax (F#)

  

嵌套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。变量ab被评估为f范围内的常量。

答案 2 :(得分:1)

let x = <val> in <expr>在功能上等同于(fun x -> <expr>) <val>

  • <expr>是一个表达式
  • <val>是一个值

in关键字是可选的。