帮我解释一下这个F#递归示例程序
这个例子来自Thomas Petricek的“面向现实世界的函数式编程” 我不理解第二个分支中的模式匹配:f rem hd。 有人能帮我吗?它调用函数f(参数之一),给出递归调用的结果和下一项帮我解释一下这个F#递归示例程序,f#,recursion,F#,Recursion,这个例子来自Thomas Petricek的“面向现实世界的函数式编程” 我不理解第二个分支中的模式匹配:f rem hd。 有人能帮我吗?它调用函数f(参数之一),给出递归调用的结果和下一项 rem是余数,或者在本例中是剩余值的结果 hd是下一项,如模式匹配的|hd::tl->部分所示 实际上,这个聚合函数包含一个函数、一个起点和一个列表。表示示例行的一种方法是: let rec aggregateList (f:int->int->int) init list = ma
rem
是余数,或者在本例中是剩余值的结果
hd
是下一项,如模式匹配的|hd::tl->
部分所示
实际上,这个聚合函数包含一个函数、一个起点和一个列表。表示示例行的一种方法是:
let rec aggregateList (f:int->int->int) init list =
match list with
| [] -> init
| hd::tl ->
let rem = aggregateList f init tl
f rem hd
let add a b = a + b
let mul a b = a * b
//to use in F# Interactive:
//aggregateList add 0 [1..5];;
它调用函数f(其中一个参数),给出递归调用的结果和下一项
rem
是余数,或者在本例中是剩余值的结果
hd
是下一项,如模式匹配的|hd::tl->
部分所示
实际上,这个聚合函数包含一个函数、一个起点和一个列表。表示示例行的一种方法是:
let rec aggregateList (f:int->int->int) init list =
match list with
| [] -> init
| hd::tl ->
let rem = aggregateList f init tl
f rem hd
let add a b = a + b
let mul a b = a * b
//to use in F# Interactive:
//aggregateList add 0 [1..5];;
让我们先分解一下
aggregateList
函数声明。该函数采用三个参数:
int
s并返回第三个int
init
的值hd
(或head),其余部分并将其分配给tl
(或tail)。然后它执行递归调用aggregateList f init tl
。当返回时,它获取结果并将其分配给rem
。然后它在rem
和hd
上调用f
当然,要小心正确选择
init
值,因为如果执行aggregateList mul 0 somelist
无论您提供什么列表,您都只会得到0
。让我们先分解聚合列表
函数声明。该函数采用三个参数:
int
s并返回第三个int
init
的值hd
(或head),其余部分并将其分配给tl
(或tail)。然后它执行递归调用aggregateList f init tl
。当返回时,它获取结果并将其分配给rem
。然后它在rem
和hd
上调用f
当然,要小心正确选择
init
值,因为如果执行aggregateList mul 0 somelist
无论您提供什么列表,您都将得到0
。为了好玩,让我们做一些printf
风格的调试:
(1 + (2 + (3 + (4 + (5 + 0)))))
看起来该函数相当于列表。foldBack(或其他语言中的fold_right
):它从右向左遍历列表中的每个项目,并调用其上的函数f
让我们以几种不同的方式重新编写函数:
> aggregateList (fun acc x -> printf "%i " x; acc + x) 0 [1..10];;
10 9 8 7 6 5 4 3 2 1 val it : int = 55
我不明白在第二分店里 模式匹配:f rem hd。能够 谁来帮帮我 那么让我们从我们已经知道的F函数开始:
是一个类型为f
的函数。传递函数时,就好像它们是int或string之类的任何其他变量一样int->int->int
- 通过传递以空格分隔的参数列表来调用函数
使用两个参数调用函数f rem hd
,f
和rem
hd
- 函数中计算的最后一个表达式被视为函数的返回值
let sum = foldBack (+) 0 [1..10] // returns 55
let sumOfSquares = foldBack (fun acc x -> acc + x * x) 0 [1..10];; // 385
在第1行中,我们使用tl
反复调用aggregateList
。由于列表越来越小,我们最终会遇到nil情况,它返回init
在第2行中,f rem hd
是函数的返回值。但是,由于我们在到达列表末尾时沿着堆栈递归,所以我们将在沿着堆栈跟踪返回时,为每个元素调用一个函数(按从右到左的顺序)
给定aggregateList(+)0[1..10]
,nil案例返回0
,因此我们调用:
- 返回值=f rem hd=f 0 10=0+10=10
- 返回值=f rem hd=f 10 9=9+10=19
- 返回值=f rem hd=f 19 8=19+8=27
- 返回值=f rem hd=f 27 7=27+7=34
- 返回值=f rem hd=f 34 6=34+6=40
- 返回值=f rem hd=f 40 5=40+5=45
- 返回值=f rem hd=f 45 4=45+4=49
- 返回值=f rem hd=f 49 3=49+3=52
- 返回值=f rem hd=f 52 2=52+2=54
- 返回值=f rem hd=f 54 1=54+1=55
55
可以想象,aggregateList
中的嵌套调用对长度n
的列表进行如下计算:
f(f(f(f(f(f(f(f)init hdn)hdn-1)hdn-2)hdn-3)…hd2)hd1)hd0仅用于f
let rec aggregateList (f:int->int->int) init list =
match list with
| [] -> init
| hd::tl ->
let rem = aggregateList f init tl // 1
f rem hd // 2