将函数作为参数传递但得到意外结果
我正在使用具有“高级学生”语言设置的 Racket,并且我在尝试编写一个函数来获取一个函数、执行它 n 次并报告每次运行所用的时间时遇到困难。这就是我到目前为止所得到的。
(define (many n fn)
(cond
[(= n 0) true]
[else (many (sub1 n) (local ((define k (time fn))) k))]))
我有一个名为 fact
的函数,它计算数字的阶乘。
(define (fact n)
(cond
[(= 0 n) 1]
[else (* n (fact (- n 1)))]))
如果我评估 (time (fact 10000))
,我会得到 cpu、实际时间和 gc 时间以及大量数字的合理结果。一切都很好。
但是,当我尝试评估 (many 3 (fact 10000))
时,我得到:
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
true
尽管作为参数传递,但为什么该函数没有评估 fact
?
I'm using Racket with the "Advanced Student" language setting and I'm having difficulty trying to write a function that takes a function, executes it n times and reports the time elapsed for each run. This is what I've got so far.
(define (many n fn)
(cond
[(= n 0) true]
[else (many (sub1 n) (local ((define k (time fn))) k))]))
I have a function called fact
that computes the factorial of a number.
(define (fact n)
(cond
[(= 0 n) 1]
[else (* n (fact (- n 1)))]))
If I evaluate (time (fact 10000))
, I get reasonable results for cpu, real and gc time, as well as a large number. All well and good.
However, when I try to evaluate (many 3 (fact 10000))
I get:
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
true
Why is the function not evaluating fact
despite being passed as a parameter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
让我们来看看
many
做了什么。首先定义它:然后调用它:当
many
递归地调用自身时,每次迭代时会发生什么:您对
many
的定义使用第一个many
的结果值递归地调用自身code>(time fn) 应用程序,但它不正确,因为您想要收集过程应用程序的计时信息,而不是值(在我们的示例中为(add1 41)
的值) )。只需在many
的定义中将true
替换为fn
:,您将得到以下结果:
您会看到
fn
> 每次递归调用都等于42
。发生这种情况是因为许多(如果不是全部)FP 语言使用应用顺序求值,并且< code>(add1 41) 在第一次调用many
发生之前进行评估。因此,我们必须使用 lambda 来确保函数(在我们的例子中是 thunk)作为第二个参数(fn )。正如您已经知道的,Scheme 中的函数应用表示为表达式周围的
()
:输出示例:
如上所示
(fn)
执行函数结果的应用(lambda () (fact 10000)
(thunk),<code>time 准确获取您想要传递给它的内容(表达式)并显示正确的计时信息。希望有所帮助。如果有请纠正我我错了。
Let's examine what you
many
does. First you defined it:Then call it:
Here what happens on every iteration when
many
calls itself recursively:Your definition of
many
recursively calls itself with the result value of the first(time fn)
application, but it is not correct, because you want to collect timing information for your procedure application, not the value (value of(add1 41)
in our case). Just substitutetrue
withfn
in your definition ofmany
:and you'll get the following:
You see that
fn
on every recursive call equals42
. This happens because many (if not all) FP languages use Applicative order of evaluation, and(add1 41)
is evaluated before the first call tomany
happens.Thus we have to use
lambda
to ensure a function (thunk in our case) is passed to many as it's second argument (fn
). As you already know function application in Scheme is expressed as()
around expression:Example output:
As you see above
(fn)
performs application of the result of function(lambda () (fact 10000)
(thunk),time
gets exactly what you wanted to pass it (an expression) and displays the correct timing information.Hope that helps. Correct me if I'm wrong.