Scheme获取列表中的最后一个元素

8

我正在尝试编写一个简单的Scheme函数,用于返回列表的最后一个元素。我的函数看起来应该能够正常工作,但是我似乎在某些地方出了问题:

(define (last_element l)(
  (cond (null? (cdr l)) (car l))
  (last_element (cdr l))
))

(last_element '(1 2 3)) should return 3

DrRacket一直给我报错:

mcdr: contract violation
  expected: mpair?
  given: ()

由于 (null? '()) 为真,我不明白为什么这样不起作用。

我认为这是我需要完成作业的一个函数(编写函数last-element不是作业),指令说我不能使用内置函数reverse,所以我不能简单地执行(car (reverse l))

我该如何修复这个函数?


如果您的函数接收到空列表会发生什么?当然,您的讲师可能不在意。他或她是否提到了您可以假设数据的内容?对于作业任务而言,我认为可以忽略非列表数据,但是在列表上下文中,空列表是可以预期的合理事物。实际上,有一种简单的方法来处理它,并且也可以合理地处理其他非列表数据... - itsbruce
4个回答

13

你的语法完全错误。你在函数体周围多了一对括号,对于cond子句来说不够用括号,并且你的递归情况甚至不在cond内部,因此它无论测试成功或失败都会执行。以下过程应该可以运行:

(define (last_element l)
  (cond ((null? (cdr l)) (car l))
        (else (last_element (cdr l)))))

6
这个答案的乐观版本是,你几乎所有的细节都正确。只要记住圆括号不同于大括号;你需要改掉在第一行打“开头括号 (()” 并将 ) 放在它们自己的一行的习惯。此外,让DrRacket指导你缩进。不久你就会掌握这些技巧。 - Greg Hendershott

8

补充一点:在专业级别的Racket中,last函数是racket/list库的一部分。


2

通过调用以下代码,您可以检索列表的最后一个元素

(define (lastElem list) (car (reverse list)))

或者采用内置if递归的方式:

(define (last list) (if (zero? (length (cdr list))) (car list) (last (cdr list))))


0
你也可以这样做。首先通过cdr操作将列表缩小,然后找到列表的长度。接着使用list-ref x来获取列表中的第x个元素。 例如,list-ref yourlistsname 0会给出第一个元素(基本上是列表的car)。而(list-ref yourlistsname (- length 1))则会给出列表的最后一个元素。

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