可以说,我有一个函数range
,该函数会逐步返回一个数字列表,我已经实现了它,并且效果很好。现在,我需要在此之上编写一个迭代器函数,因此,如果我在列表上运行迭代器函数,它将超时返回列表的第一个元素。
(define next '(1 2 3 4))
(next) => 1
(next) => 2
(next) => 3
(next) => 4
(next) => '()
我的问题是,我不知道该方案可以实现哪种语法,因为每次我们调用函数next
时,遗嘱都会刷新。但是我需要实现next函数,以便第二次在列表上调用next时,列表不会刷新,因此它将获得列表的第二项。
我是否需要了解实现此目标的任何特定方法,或者我需要修改range
函数来做到这一点。
我的迭代函数如下:
(define (iterator L)
(let ((start (car L))
(step (car (cdr L)))
(end (car (cdr (cdr L))))
)
(lambda ()
(if (> start end)
'()
(set! start
(+ start step)
)
)
)
)
)
我的下一个定义
(define next (iterator '(0 2 7)))
我收到的错误消息是:Error: execute: unbound symbol: "iterator" []
。
答案 0 :(得分:2)
对于初学者来说,您的range
代码中存在错误:
(define (range L)
(let ((start (car L))
(step (car (cdr L)))
(end (car (cdr (cdr L)))))
(if (> start end)
'() ; fix this line
(cons start (range (list (+ start step) step end))))))
现在,要创建迭代器,我们需要在过程中引入 state ,以记住迭代每个步骤中的位置。还要注意,这里有两个独立的概念:迭代器和推进它的过程,我们可以使用currying返回next
过程。这是我的建议:
(define (iter lst)
(let ((pos lst)) ; store current position
(lambda () ; return the `next` procedure
(if (null? pos) ; are we done?
'() ; then exit
(let ((cur (car pos))) ; current element
(set! pos (cdr pos)) ; advance & update state
cur))))) ; return current
像这样使用它:
(define next (iter (range '(1 1 3))))
(next)
=> 1
(next)
=> 2
(next)
=> 3
(next)
=> '()