递归理解与符号交替判断函数报错排查:first参数异常问题
解决你的Scheme函数报错与递归逻辑问题
首先,咱们先搞定那个报错:first: expects only 1 argument, but found 2。你看代码里的这两行:
[(< (first (rest lst) 0)) (alternating? (rest lst))] [(> (first (rest lst) 0)) (alternating? (rest lst))]
这里的括号嵌套错了!first只能接受一个参数(就是你要取首元素的列表),但你写成了(first (rest lst) 0),相当于给first传了两个东西:(rest lst)和0,解释器当然会报错。正确的写法应该是先取(rest lst)的首元素,再和0比较,也就是把括号调整成:
[(< (first (rest lst)) 0)] [(> (first (rest lst)) 0)]
不过光改括号还不够,你的函数还有几个逻辑漏洞,咱们一起理清楚:
递归逻辑的核心问题
判断列表符号交替的递归思路应该是:
- 边界情况:如果列表是空的,或者只有一个元素,直接返回
true(因为没有违反交替规则的元素)。 - 递归步骤:如果当前元素是正数,那下一个元素必须是负数,并且从下一个元素开始的子列表也要满足交替规则;如果当前元素是负数,下一个元素必须是正数,同时子列表也要满足规则。
- 特殊情况:如果有元素是0,直接返回
false(0既不是正也不是负,不符合交替要求)。
修正后的完整代码
(define (alternating? lst) (cond [(empty? lst) true] ; 空列表符合条件 [(empty? (rest lst)) true] ; 单个元素的列表符合条件 [(> (first lst) 0) (and (< (first (rest lst)) 0) ; 下一个元素必须是负数 (alternating? (rest lst)))] ; 递归检查子列表 [(< (first lst) 0) (and (> (first (rest lst)) 0) ; 下一个元素必须是正数 (alternating? (rest lst)))] ; 递归检查子列表 [else false])) ; 元素为0的情况,直接返回false
测试用例验证
你可以用这些check-expect来验证:
(check-expect (alternating? '(1 -2 3 -4)) true) (check-expect (alternating? '(1 2 3)) false) (check-expect (alternating? '(-1 2 -3)) true) (check-expect (alternating? '(0 1)) false) (check-expect (alternating? '(5)) true) (check-expect (alternating? '()) true)
再聊聊递归的本质
递归就是把大问题拆解成和原问题结构一致的小问题:比如判断整个列表lst是否交替,等价于判断前两个元素符号相反,并且子列表(rest lst)也满足交替条件。每次递归调用都会让列表变短,直到触发边界条件(空列表或单元素列表),递归就终止了。
你的原代码里没处理单元素列表的情况,当列表只剩一个元素时,(rest lst)是空的,这时候调用(first (rest lst))又会触发新的错误——first不能作用在空列表上,所以必须加一个分支处理单元素的情况。
内容的提问来源于stack exchange,提问作者GustoCo
相关产品推荐
相关产品推荐

