Scheme列表操作(递归)

4

这里的基本问题是,给定一个列表,返回除最后一个元素外的所有元素。例如,给定(a b c d)--> 返回(a b c)。我已经有了函数,只是在Scheme语法方面遇到了麻烦,而Google并不友好。我不确定我是否正确使用了cons。

(define all-but-last
  (lambda (x)

   (if (null? (cdr x)) 
      ('()))
   (cons ((car x) (all-but-last(cdr x)))
)))

需要熟悉R5RS Scheme语法的人会很有帮助。谢谢!

5个回答

3
如果您移除掉对“()”和“cons”的参数多余的括号,那么这段代码将能够正常工作(对于非空输入列表)。

仍然有错误,不幸的是:“mcdr:期望类型为<mutable-pair>的参数;给出()”这方面有好的资源吗?我已经通过谷歌搜索了很多,但还没有找到。 - Chris Arena
1
@Decency:你目前有什么进展?你的代码缺少当x为空列表时的边界情况。http://www.racket-lang.org/上的文档很好;对于你正在做的事情,Scheme和Racket是相同的。你也可以参考R5RS本身作为参考。 - Jeremiah Willcock
在基本情况下,您需要检查您正在查看的是否为列表。例如,(null? x) 必须是 false,以及 (pair? x)。car 不能接受空列表或非列表,cdr 可以接受所有列表,并且 cons 在第二个参数中必须有一个列表。 - caveman
1
@caveman:我相信你的意思是“cdr可以接受所有的pair(包括非空列表)”。 - Jeremiah Willcock
谢谢,这对未来会很有帮助。 - Chris Arena

2
使用支持R5RS语言的DrRacket,这个可以正常工作:
(define all-but-last
  (lambda (x)
   (if (null? x)
     '()
     (if (null? (cdr x)) 
       '()
       (cons (car x) (all-but-last(cdr x)))))))

这个可以工作,谢谢。我相信我结束了我的if语句太早了,这可能导致了问题。 - Chris Arena
1
你有一些括号放置问题。其中一个是你结束了你的“if”太早; 然而,你还在空列表'()和'cons'的参数周围有额外的一对。我预测花时间理解你得到的错误消息将在长期内得到回报。此外,像DrRacket中的“初学者”语言这样的语言将为您提供更好的错误消息,尽管如果您正在参加需要R5RS的课程,则可能无法帮助。 - John Clements
感谢上天,我终于结束了Scheme。我从未接触过像这样将括号用作其他用途的语言。对我来说,0和(0)和((0))不都是一回事,这很奇怪且不直观。 - Chris Arena

1

另一种解决方案:

(define (all-but-last xs)
  (reverse 
    (rest
      (reverse xs))))

0

这是我后来解决的一个测试问题。虽然它可能是某个人的作业,但它并不是我的作业,所以我并不在意它是否被标记为作业。 - Chris Arena

0
如果您在函数中传递 '(),我认为您应该给出错误消息而不是返回 '()。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接