Debugging 如何在SML中手动跟踪此函数?

Debugging 如何在SML中手动跟踪此函数?,debugging,recursion,racket,trace,sml,Debugging,Recursion,Racket,Trace,Sml,我试图理解SML中函数的递归调用,其目的是查找列表中的最高整数值。出于教育原因,此功能不好 fun bad_max(xs: int list) = if null xs (*if the list is empty, returns 0 which is bad style*) then 0 else if null (tl xs) (*if the list has only one element this is the max*)

我试图理解SML中函数的递归调用,其目的是查找列表中的最高整数值。出于教育原因,此功能不好

fun bad_max(xs: int list) = 
        if null xs (*if the list is empty, returns 0 which is bad style*)
        then 0
        else if null (tl xs)  (*if the list has only one element this is the max*)
        then hd xs 
        else if hd xs > bad_max(tl xs) (*not clear how this happens*)
        then hd xs
        else bad_max( tl xs)
我知道由于重复的递归调用,上面的函数以非常缓慢的方式提供正确的结果

我不明白的是最后一个else if和最后一个else是如何发生的

我真的错过了一个工具,比如跟踪,以便在递归调用中看到函数参数的变化。显然,标准ML有一个工具来实现这一点

我想了解拜访后的具体情况:

bad_max([1,7,3,4])
结果是7,这是正确的

然而,这究竟是如何发生的呢

1 > bad_max([7,3,4])
       7 > bad_max([3,4])
                3 > bad_max([4])
                3 > 4
           (*which is false*)
           (*what is the next step? Does the function come back to the int of 7?*)

       7 >      3 (*which is true!*)

                  (*or does the program go to the ELSE recursive call and restart the process such as?*)

7 > bad_max([3,4])
对不起,如果我不清楚的话。很难用文字来表达它。我试图让上面的标识表达我对递归调用语义的怀疑

我真的在寻找编程语言中存在的类似库跟踪的东西

> (define (f x) (if (zero? x) 0 (add1 (f (sub1 x)))))
> (trace f)
> (f 10)

>(f 10)

> (f 9)

> >(f 8)

> > (f 7)

> > >(f 6)

> > > (f 5)

> > > >(f 4)

> > > > (f 3)

> > > > >(f 2)

> > > > > (f 1)

> > > >[10] (f 0)

< < < <[10] 0

< < < < < 1

< < < < <2

< < < < 3

< < < <4

< < < 5

< < <6

< < 7

< <8

< 9

<10

10
关于这个疑问,有趣的是,对于我来说,列表最大值的错误解比正确的方法更难理解

====

更新:

多亏了Sorawee的评论,我得以修复上面的球拍代码:

#lang racket

(require racket/trace rackunit)

(define (bad_max lista)
 (cond ((empty? lista) 0)
       ((empty? (cdr lista)) (car lista))
       ((> (car lista)  (bad_max  (cdr lista))) (car lista))  
       (else (bad_max (cdr lista)))))

(trace bad_max)
(bad_max '(1 7 3 4))

如果您觉得需要跟踪,请一次执行一个“级别”,并使用替换方法。
(请记住,递归函数没有什么特别之处——它们的工作方式与非递归函数完全相同。)

错误\u最大值[1,7,3,4]

...
else if 1 > bad_max [7,3,4]
     then 1
     else bad_max [7,3,4]
...
else if 7 > bad_max [3,4]
     then 7
     else bad_max [3,4]
...
else if 3 > bad_max [4]
     then 3
     else bad_max [4]
...
else if 7 > 4
     then 7
     else 4
...
else if 1 > 7
     then 1
     else 7
错误\u最大值[7,3,4]

...
else if 1 > bad_max [7,3,4]
     then 1
     else bad_max [7,3,4]
...
else if 7 > bad_max [3,4]
     then 7
     else bad_max [3,4]
...
else if 3 > bad_max [4]
     then 3
     else bad_max [4]
...
else if 7 > 4
     then 7
     else 4
...
else if 1 > 7
     then 1
     else 7
错误\u最大值[3,4]

...
else if 1 > bad_max [7,3,4]
     then 1
     else bad_max [7,3,4]
...
else if 7 > bad_max [3,4]
     then 7
     else bad_max [3,4]
...
else if 3 > bad_max [4]
     then 3
     else bad_max [4]
...
else if 7 > 4
     then 7
     else 4
...
else if 1 > 7
     then 1
     else 7
现在很明显,
bad_max[3,4]
是4,因此您可以返回并替换:

错误\u最大值[7,3,4]

...
else if 1 > bad_max [7,3,4]
     then 1
     else bad_max [7,3,4]
...
else if 7 > bad_max [3,4]
     then 7
     else bad_max [3,4]
...
else if 3 > bad_max [4]
     then 3
     else bad_max [4]
...
else if 7 > 4
     then 7
     else 4
...
else if 1 > 7
     then 1
     else 7
错误\u最大值[1,7,3,4]

...
else if 1 > bad_max [7,3,4]
     then 1
     else bad_max [7,3,4]
...
else if 7 > bad_max [3,4]
     then 7
     else bad_max [3,4]
...
else if 3 > bad_max [4]
     then 3
     else bad_max [4]
...
else if 7 > 4
     then 7
     else 4
...
else if 1 > 7
     then 1
     else 7
另一方面,关于模式的推理通常比关于谓词和选择器的推理更容易:

fun bad_max [] = 0
  | bad_max [x] = x
  | bad_max (x::xs) = if x > bad_max xs
                      then x
                      else bad_max xs

你的球拍代码不起作用的原因是你忘记了帕伦斯在
carlista
。它应该是
(汽车列表a)