有关如何实现的更多信息flatten
(通常称为这种函数),请查看
至于您的具体错误,append
预计其所有(通常可能需要两个以上)参数都是列表。例如,
> (append '(1 2 3) '(4 5 6))
;=> (1 2 3 4 5 6)
> (append '(1 2 3) '(4 5 6) '(7 8 9))
;=> (1 2 3 4 5 6 7 8 9)
现在,您正在编写函数,并且您已经说过level
应该返回一个列表。这意味着如果level
有几个不同的执行路径,每个都需要生成一个列表。所以,让我们看看你的实现。
(define level
(lambda (L)
(cond ((null? L) L)
((not( pair? L)) L)
(else (append (level(car L)) (level(cdr L)))))))
在问题中,您说您正在编写一个应该采用列表的函数,因此L
可以是两件事之一;它可以是空列表,也可以是一对。不过,目前,您cond
有三个案例。
(cond ((null? L) L) ; handle an empty list
((not( pair? L)) L)
(else (append (level(car L)) (level(cdr L))))) ; handle a pair
如果您总是level
使用列表调用,则不需要第二种情况。但是,由于在第三种情况下,您确实调用了(level (car L))
,并且您不知道是否(car L)
会成为列表,因此您似乎最终会使用非列表进行调用。level
例如,您需要决定是否(level 'a)
应该合法,如果应该,应该是什么。目前,您似乎正在尝试(level 'a)
合法并返回(a)
。没关系,但您应该指定合同。如果这是您想要做的,那么您确实需要在您的第二个案例cond
,但是由于(level 'a)
应该返回(a)
,您实际上需要那个案例来返回(list L)
,而不是L
。
这里的另一个选项,如果你确实想要level
严格,并且总是需要一个列表作为参数,那么你需要添加更多的逻辑来确定它是否(car L)
是一个列表,如果是,递归调用level
它,并且打电话append
给结果。一种方法是这样的:
(define (level L)
(cond
((null? L) L)
((pair? L) (append (if (list? (car L))
(level (car L))
(list L))
(level (cdr L))))))