方案:迭代器函数一次仅返回一个值

时间:2018-07-26 03:04:35

标签: list iterator scheme

可以说,我有一个函数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" []

1 个答案:

答案 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)
=> '()