Scheme 我如何进行替换?计划
我如何进行替换?我试图追踪,但我真的不知道发生了什么。。。 守则:Scheme 我如何进行替换?计划,scheme,Scheme,我如何进行替换?我试图追踪,但我真的不知道发生了什么。。。 守则: (define (repeated f n) (if (zero? n) identity (lambda (x) ((repeated f (- n 1)) (f x))))) f是一个函数,n是一个整数,它给出了我们应用f的次数。 有人能帮我解释一下吗。我知道它会返回几个过程,我想相信它会运行f(f(f(x)) 好的,我会以不同的方式重新问这个问题,因为上次我没有得到答案。考虑这个代码 (define
(define (repeated f n)
(if (zero? n)
identity
(lambda (x) ((repeated f (- n 1)) (f x)))))
f是一个函数,n是一个整数,它给出了我们应用f的次数。
有人能帮我解释一下吗。我知道它会返回几个过程,我想相信它会运行f(f(f(x))
好的,我会以不同的方式重新问这个问题,因为上次我没有得到答案。考虑这个代码
(define (repeated f n)
(if (zero? n)
identity
(lambda (x) ((repeated f (- n 1)) (f x)))))
其中n是一个正整数,f是一个任意函数:scheme是如何在这段代码上运行的,比如我们给出(重复f2)
。会发生什么?这就是我的想法:
(f 2)
(lambda (x) ((repeated f (- 2 1)) (f x))))
(f 1)
(lambda (x) ((lambda (x) ((repeated f (- 1 1)) (f x)))) (f x))))
(f 0)
(lambda(x)(lambda(x)(恒等式(fx)))(fx)))
这里是我被卡住的第一步,我希望它(f(f(x)),但现在我将得到(λx((f x)(f x)),括号肯定是错的,但我想你明白我的意思。我关于解释器如何工作的论点有什么问题?你有一个函数,它接受一个函数
f
和一个非负整数n
,并返回函数fn,即f(f)(f(…f(n))。根据您对递归的看法,这可以通过两种方式中的任意一种直接实现。在这两种情况下,如果n为0,则您只需要一个返回其参数的函数,该函数就是标识
函数。(这是一种惯例,与x0=1的方式相同。当更深入地考虑它时,它是有意义的,但这可能超出了这个问题的范围。)
处理递归情况的方法是有一些选项。第一个选项是将fn(x)视为f(fn-1(x)),其中调用f的结果是使用x调用fn-1:
另一种选择是将fn(x)看作fn-1(f(x)),其中使用f(x)的结果调用_fn-1
在这两种情况下,这里需要注意的重要一点是,在Scheme中
(function-form arg-form-1 arg-form-2 ...)
通过计算function form
生成一个值函数值(应该是一个函数),并计算每个arg-form-i
生成值arg-value-i,然后用arg值调用函数值。因为(重复…)
生成一个函数,它适合作为函数形式
:
(f ((repeated f (- n 1)) x))
; |--- f^{n-1} ------|
; |---- f^{n-1}(x) ------|
;|------f(f^{n-1}(x)) ------|
((repeated f (- n 1)) (f x))
; |--- f^{n-1} ------|
;|---- f^{n-1}(f(x))--------|
根据Will Ness的评论,值得指出的是,虽然这些方法在某种程度上是分解这个问题的自然方法(即,基于等式fn(x)=fn-1(f(x))=f(fn-1(x))),它不一定是最有效的。这些解决方案都需要计算一些中间函数对象来表示需要相当数量存储的fn-1,然后在此基础上进行一些计算。直接计算fn(x)非常简单有效,例如,repeat
:
(define (repeat f n x)
(let rep ((n n) (x x))
(if (<= n 0)
x
(rep (- n 1) (f x)))))
(define (repeated f n)
(lambda (x)
(repeat f n x)))
这应该比其他任何一种实现都具有更好的运行时性能。您有一个函数,它接受一个函数
f
和一个非负整数n
,并返回函数fn,即f(f(…f(n)…)。根据您对递归的看法,这可以通过两种方式中的任意一种直接实现。在这两种情况下,如果n为0,则您只需要一个返回其参数的函数,该函数就是标识
函数。(这是一种惯例,与x0=1的方式相同。当更深入地考虑它时,它是有意义的,但这可能超出了这个问题的范围。)
处理递归情况的方法是有一些选项。第一个选项是将fn(x)视为f(fn-1(x)),其中调用f的结果是使用x调用fn-1:
另一种选择是将fn(x)看作fn-1(f(x)),其中使用f(x)的结果调用_fn-1
在这两种情况下,这里需要注意的重要一点是,在Scheme中
(function-form arg-form-1 arg-form-2 ...)
通过计算function form
生成一个值函数值(应该是一个函数),并计算每个arg-form-i
生成值arg-value-i,然后用arg值调用函数值。因为(重复…)
生成一个函数,它适合作为函数形式
:
(f ((repeated f (- n 1)) x))
; |--- f^{n-1} ------|
; |---- f^{n-1}(x) ------|
;|------f(f^{n-1}(x)) ------|
((repeated f (- n 1)) (f x))
; |--- f^{n-1} ------|
;|---- f^{n-1}(f(x))--------|
根据Will Ness的评论,值得指出的是,虽然这些方法在某种程度上是分解这个问题的自然方法(即,基于等式fn(x)=fn-1(f(x))=f(fn-1(x))),它不一定是最有效的。这些解决方案都需要计算一些中间函数对象来表示需要相当数量存储的fn-1,然后在此基础上进行一些计算。直接计算fn(x)非常简单有效,例如,repeat
:
(define (repeat f n x)
(let rep ((n n) (x x))
(if (<= n 0)
x
(rep (- n 1) (f x)))))
(define (repeated f n)
(lambda (x)
(repeat f n x)))
这应该比其他任何一种实现都具有更好的运行时性能。Danny。我认为,如果我们使用较小的n(0、1和2)值重复
,将能够看到函数如何转换为f(f(f(…(x))。我假设标识的实现是(define(identity x)x)
(即按原样返回其唯一参数),并且if
的“then”部分应为(标识f)
…等等。Danny。我认为,如果我们使用较小的n(0、1和2)值重复,将能够看到函数如何转换为f(f(f(…(x))。我假设标识的实现是(define(identity x)x)
(即按原样返回其唯一参数),并且“then”部分if
应该是(标识f)
…等等。您的实现实际上延迟了进一步的递归,并返回一个过程,该过程的主体将创建自身的副本以在运行时完成任务
例如:(重复双4)
==>(lambda(x)((重复双(-41))(双x))
因此,当调用它时((重复双4)2)
它会
((lambda (x) ((lambda (x) ((lambda (x) ((lambda (x) ((lambda (x) (identity x)) (double x))) (double x))) (double x))) (double x))) 2)
(define (repeat fun n)
(lambda (x)
(let repeat-loop ((n n)
(x x))
(if (<= n 0)
x
(repeat-loop (- n 1) (fun x))))))
(define (double x) (+ x x))
((repeat double 4) 2) ; ==> 32
f a b = \c -> .... === f a b c = .... ; `\ ->` is for 'lambda'
repeated f n x ; (define (repeated f n)
| n <= 0 = x ; (if (zero? n) identity
| otherwise = repeated f (n-1) (f x) ; (lambda (x)
; ((repeated f (- n 1)) (f x)))))
repeated f 2 x = ; ((repeated f 2) x) = ((\x-> ((repeated f 1) (f x))) x)
= repeated f 1 (f x) ; = ((repeated f 1) (f x))
= repeated f 0 (f (f x)) ; = ((\y->((repeated f 0) (f y))) (f x))
= f (f x) ; = ((\z-> z) (f (f x)))
; = (f (f x))