我一直在尝试使用 define-datatype 方法在方案中编写Fibonacci程序,但我无法这样做。请告诉我它是如何完成的。
我在下面写了表示独立代码:
(define (top-k k)
k)
(define (applyk k n)
(k n))
(define (fibind n k)
(cond
[(= n 0) (k 1)]
[(= n 1) (k 1)]
[else (fibind (- n 1) (fib1 n k))]))
(define fib1
(lambda (n k)
(lambda (v)
(fibind (- n 2) (lambda (w) (k (+ v w)))))))
编辑:我基本上想要一个找到斐波纳契数字的代码(类似于下面的代码)
;;;;k:: []-> continuation?
(define-datatype k k?
[topk]
[fact1-k (n number?) (saved-k k?)])
;;;appylk:: nat? continuation? -> nat?
(define apply-k
(lambda (v c)
(cases k c
[topk () v]
[fact1-k (n saved-k)
(apply-k (* n v) saved-k)])))
;;;fact :: nat? continuation? -> nat?
(define (fact n k)
(if (< n 2)
(apply-k n k)
(fact (- n 1) (fact1-k n k))))
答案 0 :(得分:4)
您的代码使您看起来像是在尝试以延续传递方式执行此操作。首先,让我们来看看实现n
斐波纳契数的天真直接方式:
(define (fib n)
;; This is a naïve implementation, and will get
;; *very* slow, *very* quickly. It's much more
;; common to implement this as an iterative process
(cond
((= n 0) 1)
((= n 1) 1)
(else (+ (fib (- n 1))
(fib (- n 2))))))
现在,为了将其转化为延续传递风格,我们只是在某些事情发生时分解。对于n
为0
或1
的情况,我们只需使用1
调用延续。但是,在递归的情况下,我们需要计算(- n 1)
的斐波那契数(称之为f1
),并用它来调用一些延续。然而,这种延续不是k
,因为仍有工作要做;我们仍然需要(- n 2)
的数字!延续使用f1
作为参数,并为我们计算(- n 2)
的斐波纳契数(称为f2
)并且必须使用它来调用某些延续。不过,这种延续也不是k
。新的续约可以访问f1
和f2
,并且它们的总和是k
所需要的:
(define (fib% n k)
(cond
((= n 0) (k 1))
((= n 1) (k 1))
(else (fib% (- n 1)
(lambda (f1)
(fib% (- n 2)
(lambda (f2)
(k (+ f1 f2)))))))))
> (fib% 1 display)
1
> (fib% 5 display)
8
> (fib% 8 display)
34
但是,有更多有效的方法来计算Fibonacci序列中的数字。典型的一个以1和1开始,然后计算下一个值(2),将其添加到前一个值(1)得到3,将前一个值(2)加到得到5,将其加到前一个值( 3)得到8,依此类推。看起来像是:
(define (fib-it n)
;; This is much more efficient, since it moves
;; computes the numbers in the sequence sequentially.
(let fib ((a 1) (b 1) (n n))
(if (zero? n)
a
(fib b (+ a b) (sub1 n)))))
除了命名的let
函数fib
返回a
而不是用它调用k
之外,这几乎已经是连续传递样式了。这可以通过以下方式完成:
(define (fib-it% n k)
(let fib ((a 1) (b 1) (n n))
(if (zero? n)
(k a)
(fib b (+ a b) (sub1 n)))))
这并不觉得它已经完成了,因为它是一个函数的延续传递样式版本,无论如何都不会进行任何自我递归调用;名为let
的迭代处理了这个问题。我们不妨写下以下内容,但这并不是很有趣:
(define (fib-it% n k)
(k (let fib ((a 1) (b 1) (n n))
(if (zero? n)
a
(fib b (+ a b) (sub1 n))))))
答案 1 :(得分:1)
以下是斐波纳契CPS表示独立的代码,
#lang racket
(define top-k
(lambda(v)
v))
(define fib
(lambda (n)
(fib/k n top-k)))
(define fib/k
(lambda (n k)
(cond
[ (= 1 n)
(apply-k k 0) ]
[ (= 2 n)
(apply-k k 1) ]
(else
(fib/k (sub1 n) (fib1-k n k) )
)
)
)
)
(define fib1-k
(lambda (n k)
(lambda(v)
(fib/k (- n 2) (fib2-k v k))
)))
(define fib2-k
(lambda(v k)
(lambda (w)
(apply-k k (+ w v))
)))
(define apply-k
(lambda(k v)
(k v)))
有关详细信息,请参阅本书Essentials of Programming Languages
的第198页我不知道你在说什么,因为独立的代表是真的如此。