如何反转Scheme中列表元素的顺序

时间:2014-09-01 12:38:06

标签: scheme lisp racket

我有一个函数来反转列表中元素的顺序,例如

(define (rvsl sequence)
  (foldl (lambda (x y) 
           (cons y x)) 
         '() sequence))

然而,当我在DrRacket中使用输入

运行它时
(rvsl (list 2 3 4))

DrRacket告诉我这个

cons: second argument must be a list, but received empty and 2

有人可以给我一些解决方法吗?

提前致谢!

3 个答案:

答案 0 :(得分:2)

您的代码存在的问题是您以错误的顺序传递参数 - 使用cons构建列表时,第一个参数是我们希望在开头时保留的新元素列表,第二个是我们到目前为止建立的列表。

话虽如此,使用foldl撤消列表有点简单,而且您根本不需要使用append - 实际上,使用{这是一种不好的做法当append足够时{1}}:

cons

为什么会这样?让我们重写这次更明确的功能:

(define (rvsl sequence)
  (foldl cons
         '()
         sequence))

现在我们可以看到(define (rvsl sequence) (foldl (lambda (current accumulated) (cons current accumulated)) '() sequence)) 过程接收到两个参数:输入列表中的lambda元素,以及到目前为止的current值 - 好的参数名称会产生重大影响。世界!这比调用参数accumulatedx要清楚得多,后者对它们一无所知。

在这种情况下,我们只想y累加值头部的当前元素(以空列表开头),因此产生一个反向列表作为输出。鉴于cons过程接收到两个参数并以相同的顺序将它们传递给lambda,我们可以简化整个过程并将cons过程作为参数传递。

答案 1 :(得分:1)

这是一个简单的版本,使用内部迭代过程。

(define (rev lst)
  (define (iter accum lst)
    (if (null? lst)
        accum
        (iter (cons (car lst) accum)
              (cdr lst))))
  (iter '() lst))

答案 2 :(得分:0)

foldl函数本身就足够了:

rev

(等式模式匹配伪代码中的注释)。推导和一些讨论here

编辑:,这显然是一个玩具代码,只是为了磨练你的Scheme-fu)。