如何在scheme/racket中使用展开编写Collatz序列?

如何在scheme/racket中使用展开编写Collatz序列?,scheme,racket,collatz,Scheme,Racket,Collatz,以常规方式写入Collatz序列生成函数后: (define (colatz-seq #;starting@ n) (cond ((= n 1) '()) ((even? n) (cons (/ n 2) (colatz-seq (/ n 2)))) ((odd? n) (cons (+ (* n 3) 1) (colatz-seq (+ (* n 3) 1)))))) 我想用“展开”来写它: (define (next-colatz-step n) (

以常规方式写入Collatz序列生成函数后:

(define (colatz-seq #;starting@ n)
  (cond ((= n 1) '())
        ((even? n) (cons (/ n 2) (colatz-seq (/ n 2))))
        ((odd? n) (cons (+ (* n 3) 1) (colatz-seq (+ (* n 3) 1))))))
我想用“展开”来写它:

(define (next-colatz-step n)
  (cond ((even? n) (/ n 2))
        ((odd? n) (+ (* n 3) 1))))

(define (one? n)
  (= n 1))

(define (colatz-seq #;starting@ n)
  (unfold one? next-colatz-step next-colatz-step n))
它可以像预期的那样工作,但是如果不使用“next colatz step”作为展开的第二个和第三个参数,我就无法让它工作。为什么?
为两个参数提供相同的参数似乎有点奇怪。

请注意,在两个解决方案中,您都排除了序列中的起始元素,而在基于
展开的解决方案中,生成的序列在某种程度上落后于一个位置,这就是为什么您必须两次通过
下一个colatz步骤

如果我们从给定的
n
数字开始,那么
unfold
的第二个参数就是
identity
过程,这似乎更自然。但这就给我们留下了一个问题,即最后一个值(假定Collatz猜想为真,则该值应始终为
1
)现在丢失了。这就是为什么现在我们必须提供一个额外的过程来生成列表的尾部。试试这个:

(require srfi/1)

(define (one? n)
  (= n 1))

(define (next-collatz-step n)
  (cond ((even? n) (/ n 2))
        (else (+ (* 3 n) 1))))

(define (last-value n)
  (list n))

(define (collatz-seq n)
  (unfold one? identity next-collatz-step n last-value))

(collatz-seq 10)
=> '(10 5 16 8 4 2 1)

为什么:
(定义(一个n)(列表1))
将n作为参数,即使它不被使用?@X10D这是因为
展开
希望将一个arg过程作为其最后一个参数,但我们已经知道最后一个值必须是
1
。但是,我更新了它以使用参数,在递归中的该点
n
1
。也可以将
collatz seq
的主体写为
(展开一个?标识下一个collatz步骤n列表)