myList是一个列表,其元素既可以是myList的相同类型的符号或列表。 例如:myList ='(a b(a d c)d())等等
我想在Scheme中编写一个只会遍历它的函数(最终我将用其他值替换符号)。
我写了这个函数:
(define traversal (lambda (myList)
(if (null? myList) '()
(if (and (list? (car myList)) (not (null? (car myList))))
(list (traversal (car myList)) (traversal (cdr myList)))
; else if car is an empty list
(if (null? (car myList))
(list (traversal (cdr myList)))
; else car is a symbol
(append (list (car myList)) (traversal (cdr myList))))))))
它为myList的某些配置提供了正确的结果,但绝对不是那个。 例如,
(display (traversal '((f) h (r t b) (x m b m y) b (c (d)))))
增加了我不需要的附加功能。
显示此类列表的正确方法是什么?
答案 0 :(得分:1)
您接近解决方案。以下是一些提示:
而不是嵌套if
尝试使用cond
表单,它更具可读性。
表达式(and (list? (car myList)) (not (null? (car myList))))
是正确的,但您可以使用更短的(pair? (car myList))
并执行几乎相同的操作。
traversal
应返回一个列表,但在此处使用带有列表参数的list
(list (traversal (car myList)) (traversal (cdr myList)))
将返回列表列表。例如。 (list '(a) '(b))
将返回((a) (b))
而不是(a b)
。在这些情况下,您应该使用append
(append '(a) '(b))
- > (a b)
。
如果值不是列表但您想将其添加到现有列表,请使用cons
过程。
(cons 'a '(b c))
- > (a b c)
。
答案 1 :(得分:1)
null?
,其中一次测试通常就足够了。 list
,而只是cons
。append
,此处不需要。{/ li>
(car ...)
表单优化let
的重复使用。代码的简化形式为:
(define traversal
(lambda (myList)
(if (null? myList)
'()
(let ((c (car myList)))
(cons (if (list? c) (traversal c) c)
(traversal (cdr myList)))))))
修改强>
虽然此过程适用于正确的列表,但它不适用于不正确的列表(尽管看起来如此)。以下是一种更通用的方法,适用于各种S-expression,包括正确的列表,我建议使用以上代码:
(define traversal
(lambda (sexp)
(cond
((null? sexp) '())
((pair? sexp) (cons (traversal (car sexp))
(traversal (cdr sexp))))
(else sexp))))