1

我对方案和汽车、cdr 等的想法非常陌生。我有这个函数来返回列表的最后一个元素,但现在它只返回一个空列表。

 (define (last mylist)
      (if (list? mylist)
              (if (null? mylist)
                  (if (null? (cdr mylist))
                      '()
                      (last (cdr mylist)) 
                   )
              )        
      )
)
4

5 回答 5

2

如何设计程序》一书通过给你一个具体而详细的设计秘诀来帮助你回答这个问题。这个特殊问题在第 9.2 节“非空列表”中进行了介绍。总的来说,以下是您需要遵循的步骤:

  • 为非空列表制定数据定义(或从书中获取)
  • 为您的函数编写目的声明、签名和标题
  • 编写测试用例(您的测试用例在这里会有很大帮助。(请记住,您不需要测试数据定义不允许的输入)
  • 添加与您的数据定义关联的模板(也出现在书中)
  • 填写模板中的空白处以完成您的定义
  • 调试。
于 2017-11-02T21:16:38.937 回答
2

仅凭你的缩进,很明显你是从另一种编程语言来到 Scheme

但是你也用if错了——在Scheme中,你不能有一个单分支 if语句。好吧,Scheme 中根本没有语句,只有表达式,而if表达式总是需要 3 个操作数(参数)

  1. 谓词(条件)
  2. 结果(如果谓词为真会发生什么
  3. 替代方案(当谓词为假时会发生什么)

你的程序很接近。只需稍作调整,您就可以到达您需要的位置 - 请注意缩进如何让您轻松查看if3 个操作数。

(define (last mylist)
  (if (null? mylist)
      #f
      (if (null? (cdr mylist))
          (car mylist)
          (last (cdr mylist)))))

最后,Scheme 提供cond了有助于防止对条件序列进行不必要的代码嵌套

(define (last mylist)
  (cond ((null? mylist)
         #f)
        ((null? (cdr mylist))
         (car mylist))
        (else
         (last (cdr mylist)))))

(last '())
;; #f

(last '(1))
;; 1

(last '(1 2))
;; 2

(last '(1 2 3))
;; 3

这个答案的范围之外是返回值#f——(last '())我认为调用last空列表应该与调用空列表具有相同的效果car。但我会把它留给你。

于 2017-11-02T21:53:22.897 回答
1

当你问这个问题时,如果那是真的(null? (cdr mylist)),你应该返回而不是. 因为那时它意味着这是一个单原子列表。(car mylist)'()mylist

(define (last mylist)
  (cond ((null? mylist) '())
        ((null? (cdr mylist)) (car mylist))
        (else (last (cdr mylist)))))

您可以使用cond而不是if避免嵌套条件,因为当您只有两个条件选项时,通常使用cond处理多个手臂。if

Little Schemer这本书最能帮助我想象一个 Scheme 程序中正在发生的事情。

于 2017-11-04T00:10:24.743 回答
1

如果(null? mylist)不成立,那是什么?非空列表。

非空列表可能有一个或多个元素。

有多少元素有这样的列表,它们的最后一个元素是它们的第一个?

关于这样的清单可以说什么cdr?您应该使用它来更早地停止递归。现在它会一直持续到列表为空,但您需要在此之前停止。

(define (last mylist)
      (if (list? mylist)
              (if (null? mylist)
                  '()
                  ;; {1}
                  (last (cdr mylist))
                  ;;
                  )))

{1}(last (cdr mylist))无条件地打电话。但是,如果您已经到达列表的末尾怎么办?如果只剩下一个元素怎么办?在这种情况下,您需要将作为结果返回。if因此,用表达式替换无条件代码来完成此操作。

于 2017-11-02T20:22:47.963 回答
0

我认为这最接近您的初始代码:

(define (last mylist)
  (if (list? mylist)
      (if (null? mylist)
          '() ; input list is empty
          (if (null? (cdr mylist))
              (car mylist) ; list only has one remaining element so this is it
              (last (cdr mylist)))) ; otherwise, recurse
      #f)) ; input is not a list

使用时if,请务必始终填写正确错误的分支。

于 2017-11-03T05:42:49.577 回答