- 💭 写在前面:本章我们将讲解支持匿名函数,先回顾一下 F# 语言表示函数的方法,然后引出它。随后我们讲解一下如何设计递归函数,最后让我们的 F- 语言支持递归函数。
目录
0x00 回顾:F# 语言
0x01 支持匿名函数:fun x → E
0x02 设计递归函数
0x03 支持递归函数:let rec ...
0x00 回顾:F# 语言
在F#教程中,我们可以使用 fun -> …
的语法来表示一个函数。
注意,这样的函数可以在不命名的情况下定义和使用。
在下面的示例中,函数 fun x -> x + 1
和 fun x -> x * 2
没有函数名。
因此,这些被称为 匿名函数 (anonymous function),或 lambda 函数 ()。
let add = fun x y -> x + y
let n = add 2 3
let m = (fun x -> x + 1) 4 // 这么写也可以
let l = List.map (fun x -> x * 2) [1; 2; 3]
0x01 支持匿名函数:fun x → E
让我们将这个特性引入到我们的 F- 语言中。
我们可以拓展我们的语法,以包含 形式,定义这个表达式的语义是直接的。
有了 的语法,实际上我们的语言就不再需要 let f x = E1 in E2 的语法了。
但是,为了用户方便,我们仍然会保留 let f x = ... 的语法。
0x02 设计递归函数
接下来,让我们考虑递归函数。请注意,之前的函数定义和应用的语义无法支持递归。
函数定义的语义:
函数应用的语义:
根据之前的定义, 是一个函数,在闭包中捕获了一个空环境 ( { } ) 。
在评估 4 时,函数体 if ... else ... 在 下被评估:函数名 没有被绑定。
0x03 支持递归函数:let rec ...
现在,让我们来让 F- 语言支持递归,引入新语法 let rec ... 来定义递归函数。
现在,一个值也可以是递归函数:
它是一个元祖,包含函数名、参数名、函数体表达式以及捕获的环境。
函数引用的语义也必须更新,现在我们必须有两个单独的推理规则来推导
若 被评估为一个递归函数,我们必须更新 ,同时绑定 和 .
常规函数的应用:
递归函数的应用:
让我们回到之前的例子,确定我们的新语义是否起作用。
在新的语义中, 被绑定到一个递归函数值 〈𝒇, 𝒙, if … else … ,{ }〉
现在递归函数的应用也起作用了:
- 在对 f 4 进行评估时,在 {𝒙 ↦ 𝟒, 𝒇 ↦ 〈𝒇, 𝒙, if … else … ,{ }〉} 下评估函数体 if ... else ... :现在 f 被绑定了,所以这个表达式可以成功地进行评估。
📌 [ 笔者 ] 王亦优
📃 [ 更新 ] 2024.6.10
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!
📜 参考资料 Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. . |