Recursion let如何在这个函数中工作?
此函数用于查找列表的最大编号,我很难理解它:Recursion let如何在这个函数中工作?,recursion,functional-programming,sml,Recursion,Functional Programming,Sml,此函数用于查找列表的最大编号,我很难理解它: fun max1 (xs : int list) = if null xs then NONE else let val tl_ans = max1(tl xs) in if isSome tl_ans andalso valOf tl_ans > hd xs then tl_
fun max1 (xs : int list) =
if null xs
then NONE
else
let val tl_ans = max1(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
then
tl_ans
else
SOME (hd xs)
end;
如果是一些tl和ALSO valOf tl ans>hd xs
既然还没定下来? 该函数有两种情况: 1) 基本案例-列表为空 没有最大值,返回
NONE
2) 列表不为空-由于列表不为空,列表将有一个头部(第一个元素)和一个尾部(除第一个元素外的所有元素)。请注意,对于包含一个元素的列表,尾部将为空
这里的想法是,对于非空列表,递归地计算列表尾部的最大值,tl_ans
(“尾部答案”或尾部中的最大值)。因为我们知道除了第一个元素(head)之外的所有元素中的最大值,所以整个列表的最大值就是tl_ans
和列表的head之间的最大值
在每次递归调用中,输入大小减少1,因为我们只是传递列表的尾部(即没有第一个元素)。当它得到一个只有一个尾部为空的元素的列表时,它将最终调用基本情况。从那里,在每次递归调用返回的过程中,该递归调用的头将与递归返回的头进行比较
下面是一个例子:
最大值[5,2,6,4]
tl_ans = max [2,6,4], hd = 5
|
|=>tl_ans = max [6,4], hd = 2
|
|=>tl_ans = max [4], hd = 6
|
|=>tl_ans = max [], hd = 4
|
|<= None (Base case)
<= Some 4, comparing tl_ans (None) and hd (4)
<== Some 6, comparing tl_ans (Some 4) and hd (6)
<= Some 6, comparing tl_ans (Some 6) and hd (2)
<= Some 6, comparing tl_ans (some 6) and hd (5)
tl_ans=max[2,6,4],hd=5
|
|=>tl_ans=max[6,4],hd=2
|
|=>tl_ans=max[4],hd=6
|
|=>tl_ans=max[],hd=4
|
| 该函数有两种情况:
1) 基本案例-列表为空
没有最大值,返回NONE
2) 列表不为空-由于列表不为空,列表将有一个头部(第一个元素)和一个尾部(除第一个元素外的所有元素)。请注意,对于包含一个元素的列表,尾部将为空
这里的想法是,对于非空列表,递归地计算列表尾部的最大值,tl_ans
(“尾部答案”或尾部中的最大值)。因为我们知道除了第一个元素(head)之外的所有元素中的最大值,所以整个列表的最大值就是tl_ans
和列表的head之间的最大值
在每次递归调用中,输入大小减少1,因为我们只是传递列表的尾部(即没有第一个元素)。当它得到一个只有一个尾部为空的元素的列表时,它将最终调用基本情况。从那里,在每次递归调用返回的过程中,该递归调用的头将与递归返回的头进行比较
下面是一个例子:
最大值[5,2,6,4]
tl_ans = max [2,6,4], hd = 5
|
|=>tl_ans = max [6,4], hd = 2
|
|=>tl_ans = max [4], hd = 6
|
|=>tl_ans = max [], hd = 4
|
|<= None (Base case)
<= Some 4, comparing tl_ans (None) and hd (4)
<== Some 6, comparing tl_ans (Some 4) and hd (6)
<= Some 6, comparing tl_ans (Some 6) and hd (2)
<= Some 6, comparing tl_ans (some 6) and hd (5)
tl_ans=max[2,6,4],hd=5
|
|=>tl_ans=max[6,4],hd=2
|
|=>tl_ans=max[4],hd=6
|
|=>tl_ans=max[],hd=4
|
| 台词
let val tl_ans = max1(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
在以下代码中,让tl_ans
的值为max1(tl xs)
。
(您通常会说max1(tlxs)
的值绑定到名称(或变量)“tl_ans”。)
它的意思和
if isSome (max1 (tl xs)) andalso valOf (max1 (tl xs)) > hd xs
除了值max1(tl-xs)
只计算一次以外。行
let val tl_ans = max1(tl xs)
in
if isSome tl_ans andalso valOf tl_ans > hd xs
在以下代码中,让tl_ans
的值为max1(tl xs)
。
(您通常会说max1(tlxs)
的值绑定到名称(或变量)“tl_ans”。)
它的意思和
if isSome (max1 (tl xs)) andalso valOf (max1 (tl xs)) > hd xs
除了值max1(tl xs)
只计算一次之外。这不是用标准ML编写此类函数的最惯用方法。我建议,用另一种方法编写它可以更好地理解它的工作原理。函数valOf
、hd
和tl
都是所谓的,使用它们的唯一借口是确保它们的输入分别不是NONE
或[]
(在这种情况下,程序将调用异常)
因此,使用valOf
,hd
或tail
将要求您检查列表是否为空(例如null xs
)或存在选项(例如是一些ans
),因此使用它的便利性受到限制。相反,需要使用模式匹配(或这些函数的更健壮版本)
下面我用另外两种方法编写了相同的函数,其中一种类似于您提供的函数
(* For a list with at least one element in it, check to see if there is a
* greatest element in the tail (xs). If there isn't, then x is the greatest
* element. Otherwise, whichever is the greatest of x and y is the greatest.
*
* This solution is comparable to the one you have above: Find a solution
* for the "smaller" problem (i.e. the reduced list in which x isn't in),
* and then combine the solution. This means making a recursive call to a
* function that doesn't exist at the time of writing it. *)
fun max [] = NONE
| max (x::xs) =
(case max xs of
NONE => SOME x
| SOME y => SOME (Int.max (x, y)))
(* If we were to use a let-expression instead of a case-of, but still restrict
* ourselves from using partial functions, we might make a helper function: *)
fun maxOpt (x, NONE) = SOME x
| maxOpt (x, SOME y) = SOME (Int.max (x, y))
(* Now the essence of the let-expression is boiled down: It finds the largest
* value in the tail, xs, and if it exists, finds the largest of that and x,
* and pass it as a result packed in SOME. *)
fun max [] = NONE
| max (x::xs) =
let val y_opt = max xs
in maxOpt (x, y_opt) end
(* In fact, one can store the largest value so far in the front of the list.
* This is only because the return type is int option, and the input type is
* int list. If the return type were dramatically different, it might not be
* so easy. *)
fun max [] = NONE
| max (x::y::xs) = max (Int.max (x,y)::xs)
| max [x] = SOME x
用标准ML编写这样一个函数,这不是最惯用的方法。我建议用另一种方法编写它,可以更好地理解它的工作原理。函数valOf
、hd
和tl
都是所谓的,使用它们的唯一借口是确保它们的输入分别不是NONE
或[]
(在这种情况下,程序将调用异常)
因此,使用valOf
,hd
或tail
将要求您检查列表是否为空(例如null xs
)或存在选项(例如是一些ans
),因此使用它的便利性受到限制。相反,需要使用模式匹配(或这些函数的更健壮版本)
下面我用另外两种方法编写了相同的函数,其中一种类似于您提供的函数
(* For a list with at least one element in it, check to see if there is a
* greatest element in the tail (xs). If there isn't, then x is the greatest
* element. Otherwise, whichever is the greatest of x and y is the greatest.
*
* This solution is comparable to the one you have above: Find a solution
* for the "smaller" problem (i.e. the reduced list in which x isn't in),
* and then combine the solution. This means making a recursive call to a
* function that doesn't exist at the time of writing it. *)
fun max [] = NONE
| max (x::xs) =
(case max xs of
NONE => SOME x
| SOME y => SOME (Int.max (x, y)))
(* If we were to use a let-expression instead of a case-of, but still restrict
* ourselves from using partial functions, we might make a helper function: *)
fun maxOpt (x, NONE) = SOME x
| maxOpt (x, SOME y) = SOME (Int.max (x, y))
(* Now the essence of the let-expression is boiled down: It finds the largest
* value in the tail, xs, and if it exists, finds the largest of that and x,
* and pass it as a result packed in SOME. *)
fun max [] = NONE
| max (x::xs) =
let val y_opt = max xs
in maxOpt (x, y_opt) end
(* In fact, one can store the largest value so far in the front of the list.
* This is only because the return type is int option, and the input type is
* int list. If the return type were dramatically different, it might not be
* so easy. *)
fun max [] = NONE
| max (x::y::xs) = max (Int.max (x,y)::xs)
| max [x] = SOME x