让我们来看看你many 做了什么。首先你定义它:
(define (many n fn)
(cond
[(= n 0) true]
[else (many (sub1 n)
(local ((define k (time fn)))
k))]))
然后调用它:
> (many 3 (add1 41))
cpu time: 0 real time: 0 gc time: 0
cpu time: 0 real time: 0 gc time: 0
cpu time: 0 real time: 0 gc time: 0
#t
>
当many 递归调用自身时,每次迭代会发生什么:
(define (many 3 42)
(cond
[(= 3 0) true]
[else (many (sub1 3)
(local ((define k (time 42)))
42))]))
(define (many 2 42)
(cond
[(= 2 0) true]
[else (many (sub1 2)
(local ((define k (time 42)))
42))]))
(define (many 1 42)
(cond
[(= 1 0) true]
[else (many (sub1 1)
(local ((define k (time 42)))
42))]))
(define (many 0 42)
(cond
[(= 0 0) true]
[else (many (sub1 0)
(local ((define k (time 42)))
42))]))
你对many的定义递归调用了第一个(time fn)应用程序的结果值,但是不正确,因为你想为你的程序应用程序收集计时信息,而不是值(@987654329的值@ 在我们的例子中)。只需在 many 的定义中将 true 替换为 fn:
(define (many n fn)
(cond
[(= n 0) fn]
[else (many (sub1 n)
(local ((define k (time fn)))
k))]))
你会得到以下结果:
> (many 3 (add1 41))
cpu time: 0 real time: 0 gc time: 0
cpu time: 0 real time: 0 gc time: 0
cpu time: 0 real time: 0 gc time: 0
cpu time: 0 real time: 0 gc time: 0
42
>
您会看到,每次递归调用中的fn 都等于42。发生这种情况是因为许多(如果不是全部)FP 语言使用Applicative order 进行评估,并且(add1 41) 在第一次调用many 之前被评估。
因此我们必须使用lambda 来确保函数(在我们的例子中为thunk)作为第二个参数(fn)传递给许多人。如您所知,Scheme 中的函数应用表示为 () 周围的表达式:
(define (many n fn)
(time (fn))
(if (= n 0)
true
(many (sub1 n) fn)))
示例输出:
> (many 3 (lambda () (fact 10000)))
cpu time: 2734 real time: 2828 gc time: 1922
cpu time: 906 real time: 953 gc time: 171
cpu time: 891 real time: 953 gc time: 204
cpu time: 938 real time: 984 gc time: 251
#t
>
正如您在上面看到的(fn) 执行函数(lambda () (fact 10000)(thunk)的结果的应用,time 得到您想要传递的内容(一个表达式)并显示正确的时间信息。
希望对您有所帮助。如果我错了,请纠正我。