List 用于反转列表的Scheme函数

List 用于反转列表的Scheme函数,list,scheme,reverse,List,Scheme,Reverse,对于我的编程语言类,我应该在Scheme中编写一个函数来反转列表,而不使用预先制作的反转函数。到目前为止,我得到的是 (define (reverseList lst) (COND ((NULL? lst) '()) (ELSE (CONS (reverseList(CDR lst)) (CAR lst))) )) 我遇到的问题是,如果我输入一个列表,比如说(abc),它会给我((().c.b).a) 如果没有多组括号和我怎么才能得到一个干净的列表呢?您的实现的问题是cons没有接收列表作为其

对于我的编程语言类,我应该在Scheme中编写一个函数来反转列表,而不使用预先制作的反转函数。到目前为止,我得到的是

(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
我遇到的问题是,如果我输入一个列表,比如说
(abc)
,它会给我
((().c.b).a)


如果没有多组括号和
我怎么才能得到一个干净的列表呢?

您的实现的问题是
cons
没有接收列表作为其第二个参数,因此您构建的答案不是一个正确的列表,记住:正确的列表是通过
cons
ing一个元素与一个列表来构造的,最后一个列表是空的

一种可能的解决方法是使用辅助函数,在累加器参数中构建答案,
cons
将元素反向排列-顺便说一句,此解决方案是尾部递归的:

(define (reverse lst)
  (reverse-helper lst '()))

(define (reverse-helper lst acc)
  (if (null? lst)
      acc
      (reverse-helper (cdr lst) (cons (car lst) acc))))

(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)

你已经走到一半了。结果中元素的顺序是正确的,只有结构需要修复

您需要执行此转换:

 (((() . c) . b) . a)           ; input
 --------------------
 (((() . c) . b) . a)   ()      ; trans-
  ((() . c) . b)       (a)      ;      for-
   (() . c)          (b a)      ;         mation
    ()             (c b a)      ;               steps
      --------------------
                   (c b a)      ;               result
这很容易编码。我们可以立即获得中间值的
car
cdr
。在每一步中,下一个中间结果由
(cons(cdr中间值)中间结果)
构造,而
中间结果
启动为空列表,因为这是我们在这里构造的-列表:

中间结果
用作累加器。这就是所谓的“累加器技术”<代码>步骤表示使用“命名let”语法编码的循环步骤

因此,总体上相反

(define (my-reverse lst)
   (transform-rev 
       (reverseList lst)))

您能否调整
transformrev
,使其能够接受原始列表作为输入,从而跳过
reverseList
调用?您只需要更改数据访问部分,即如何获得下一个临时值,以及向临时结果中添加的内容

逐步浏览列表,并将列表的car追加到递归调用中

(define (my-reverse L)
 (fold cons '() L)) ;;left fold
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR      lst))))
))

你明白每个
的意思吗?为什么会看到这么多括号?这里的答案将为你指出一个正确的解决方案,Willence的解决方案涵盖了你所看到的,但你也可能从中受益,并且。您可能也会发现这很有用。请更改算法。您的算法是在反向列表的头部插入一个空列表。它一直这样做是为了部分反转。我想你的意思是把列表连接起来,这样你就得到了一个平面列表,作为一个列表列表的结果。。。名单的一部分。使用append而不是consum你能详细说明你的答案吗?这被标记为低质量。@CodeMaverick折叠以初始值(
”()
开始,然后使用给定函数(
cons
在这种情况下)为列表中的每个项目更新该值(在左折叠的情况下从左到右)。由于
cons
从右到左构建列表,并且由于输入元素从左到右来自传入列表(由于左折叠),因此生成的列表与原始列表相反。类似地,您可以使用右折叠来复制列表,右折叠从右到左获取输入元素。使用
append
来构建列表有点不受欢迎,这意味着您没有以正确的方式重复出现。此外,这是可怕的效率低下,想想看。大多数时候你想使用cons和tail递归来建立一个列表,请看我的答案。这是一篇非常有趣的文章。我想我是众多有基本缺陷的毕业生之一:-)谢谢。助手功能有什么原因或好处吗?在我看来,您可以将其代码放入原始函数中,[将acc替换为“()”,这样一切都可以正常工作?我将其作为助手编写,因为原始函数只接收一个参数,但我们需要两个参数来实现尾部递归。通常我会将其编写为命名的
let
,以避免创建两个函数,但这可能更难理解,因为OPin lisp append不是低效的,您不是在移动数据,只是在设置指针。不管奥斯卡·洛佩兹说什么。该算法是正确的,所以它是正确的。
反向帮助程序
的更好名称是,因为该函数在SRFI 1中被调用,它看起来不像是人工帮助程序,更像是真实的函数。:-)
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR      lst))))
))