我有以下项目
(define itemslist
(list 'a1 'b2 'c3 (list 'z1 'z2) 'd5 'e6))
我找到项目的方法如下
(define find-item
(lambda (item itemslist)
(cond ((null? itemslist) #f)
((list? (car itemslist))
(cond ((null? itemslist) #f)
(else (find-item item (car itemslist)))))
((equal? stn (car itemslist)) (display "found"))
(else (find-stn stn (cdr itemslist)))
)
)
)
通过上面的方法,我可以找到a1,b2,c3,z1,z2。但是当我想要找到d5之后,它什么也没有返回。它似乎跳过了堆栈。顺便说一句,我刚刚开始学习Scheme,所以简单的解释会更好。
还有一个qns,如果我有这个怎么样
(list 'a1 'b2 'c3 (list 'z1 (list 'y1 'y2) 'z2) 'd5 'e6)
这也有效吗?谢谢!
答案 0 :(得分:4)
是的,你跳过列表 例如:
'(1 '(2 3) 4)
如果(list? '(2 3))
为真,则else
部分(外部cond
)将不会被评估,因此会跳过4
。
因此,要么将else
部分放在list?
块内,要么重新设计代码。
如果itemlist
是list/pair
,您可以在递归通话中立即传递
你可以避免在谓词中编写像(car itemslist)
这样的代码,从而使代码变得简单。
这是一个经过重新设计(简化)的版本:
(define (find-item item l)
(cond ((equal? item l) #t)
((pair? l) (or (find-item item (car l)) (find-item item (cdr l))))
(else #f)))
提示:您也可以使用'(...)
符号而不是(list ...)
来编写列表,即
(find-item 'z2 '('a1 'b2 'c3 '('z1 '('y1 'y2) 'z2) 'd5 'e6))
#t
(find-item 'e6 '('a1 'b2 'c3 '('z1 '('y1 'y2) 'z2) 'd5 'e6))
#t
答案 1 :(得分:2)
为了写更多而写更多...这通常被称为“树行走”,因为像这样的嵌套列表实际上是二叉树。列表实际上由二进制对组成,因此当您有一对(l . r)
时,l
是树的左分支,r
是树的右分支。
例如,'(1 (2 3) 4)
是'(1 . ((2 . (3 . ())) . (4 . ())))
的缩写,可以绘制为
.
/ \
1 .
/ \
/ .
/ / \
. 4 ()
/ \
2 .
/ \
3 ()
并且在(l . r)
对,car
为您提供左侧树,cdr
为您提供权利。所以,当你写(pair? ls)
时,你真的在问你是否在树的一个分支处,此时你应该在左分支(car
)和右分支上重复( cdr
)。希望能帮助您理解列表。
答案 2 :(得分:0)
即使你得到了[具体]答案,这里有一些可以帮助你解决类似问题的事情。
(define describe
(lambda (e)
(cond #;((list? e)
`(list ,@(map describe e)))
((pair? e)
`(cons ,(describe (car e))
,(describe (cdr e))))
((vector? e)
`(vector ,@(map describe (vector->list e))))
((or (null? e) (symbol? e)) `',e)
(else e))))
此过程打印生成给定sexpr的代码。例如:
> (describe '(a 2 b 3))
(cons 'a (cons 2 (cons 'b (cons 3 '()))))
它还会将引号放在需要的位置,因此它将它们放在符号或()之前,但不放在数字之前。如果您熟悉嵌套对,则可能需要删除第三行上的#;
,以生成更紧凑的输出:
> (describe '(a 2 b 3))
(list 'a 2 'b 3)
这段代码可以教你很多关于引用的东西。例如:
> (describe ''''a)
(list 'quote (list 'quote (list 'quote 'a)))