Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion let如何在这个函数中工作?_Recursion_Functional Programming_Sml - Fatal编程技术网

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