[英]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:
大致来说,这是您需要遵循的步骤:
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个操作数(参数)
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
,请务必始终填写true和false分支。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.