简体   繁体   English

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

[英]scheme getting the last element in a list

Im very new to scheme and the ideas of car, cdr, etc. I have this function to return the last element of a list, but right now it just returns an empty list. 我对方案和有关car,cdr等的想法非常陌生。我具有此功能以返回列表的最后一个元素,但现在它仅返回一个空列表。

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

The book How To Design Programs helps you answer this problem by giving you a specific and detailed design recipe. 如何设计程序 》一书您提供了具体而详细的设计秘诀,可帮助您解决此问题。 This particular problem is covered in section 9.2, "Non-empty Lists". 第9.2节“非空列表”涵盖了此特定问题。 Broadly, here are the steps you need to follow: 大致来说,这是您需要遵循的步骤:

  • formulate a data definition for non-empty lists (or take it from the book) 为非空列表制定数据定义(或从书中获取数据定义)
  • write the purpose statement, signature, and header for your function 编写函数的用途声明,签名和标头
  • WRITE TEST CASES (your test cases are going to help a lot here. (keep in mind that you don't need to test inputs that aren't allowed by your data definition) 编写测试用例(测试用例都将有很大的帮助在这里。(记住,你不需要测试不是由您的数据定义允许输入)
  • add the template associated with your data definition (also appears in the book) 添加与您的数据定义关联的模板(也出现在书中)
  • fill in the blank places in the template to complete your definition 填写模板中的空白位置以完成定义
  • debug. 调试。

By your indentation alone, it's very evident that you're coming to Scheme from another programming language 仅凭您的缩进,就很明显,您是从另一种编程语言进入Scheme的。

But you're also using if incorrectly – in Scheme, you cannot have a single-branch if statement. 但是, if您使用的if错误,那么在Scheme中,您不能使用单分支 if语句。 Well, there's no statements in Scheme at all, only expressions , and if expressions will always take 3 operands (arguments) 好的,Scheme中根本没有语句 ,只有表达式 ,并且if表达式将始终使用3个操作数(参数)

  1. the predicate (condition) 谓词 (条件)
  2. the consequent (what happens if the predicate is true) 结果 (如果谓词为真会发生什么)
  3. the alternative (what happens when the predicate is false) 备选方案 (谓词为假时会发生什么)

Your program is close tho. 您的程序已关闭。 Just a little adjustment and you're right where you need to be – take note of how the indentation makes it easy to see if 's 3 operands. 只是一个小的调整,你是正确的,你需要的是-采取的压痕如何可以很容易地看到音符if的3个操作数。

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

Lastly, Scheme offers cond that helps prevent unnecessary code nesting for sequences of conditions 最后,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

Beyond the scope of this answer is the return value #f for (last '()) – I would argue that calling last on an empty list should have the same effect of calling car on an empty list. (last '())的返回值#f超出了此答案的范围–我认为在空列表上调用last应该具有在空列表上调用car的相同效果。 But I'll leave it up to you. 但我会留给你。

If (null? mylist) does not hold, what is it? 如果(null? mylist)不成立,那是什么? A non-empty list. 非空列表。

Non-empty lists may have one, or more, elements. 非空列表可以具有一个或多个元素。

How many elements have such lists that their last element is their first? 有多少个元素具有这样的列表,它们的最后一个元素是第一个?

What can be said about such lists' cdr ? 关于这样的列表的cdr可以说些什么? You should use this to stop your recursion earlier. 您应该使用它来停止您的递归。 Right now it continues until the list is empty, but you need to stop earlier than that. 现在,它将继续直到列表为空,但是您需要在此之前停止。

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

at {1} you call (last (cdr mylist)) unconditionally. {1}您无条件致电(last (cdr mylist)) But what if you've reached the end of your list? 但是,如果您到达列表末尾怎么办? What if only one element is left? 如果只剩下一个元素怎么办? You'll need to return it as the result, in such case. 在这种情况下,您需要将作为结果返回。 So, replace the unconditional code with an if expression to accomplish this. 因此,用if表达式替换无条件代码即可完成此操作。

When you asked the question (null? (cdr mylist)) , you should have returned (car mylist) if that's true instead of '() . 当您问这个问题(null? (cdr mylist)) ,您应该返回(car mylist)的确是真,而不是'() Since at that point it means that mylist is a single-atom list. 从那时起,这意味着mylist是一个单原子列表。

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

You could use cond instead of if to avoid nested conditions, since cond handle many arms while if is often used for when you have only two options for a condition. 您可以使用cond代替if来避免嵌套条件,因为cond处理许多分支,而if则通常用于条件只有两个选项的情况。

This book the Little Schemer did best at helping me visualize what's going on in a Scheme program. Little Schemer的这本书最擅长帮助我可视化Scheme程序中发生的事情。

I think this comes closest to your initial code: 我认为这最接近您的初始代码:

(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

When using if , be sure to always fill out both the true and the false branches. 使用if ,请务必始终填写truefalse分支。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM