方案——n元减法函数问题
Scheme - n-ary subtraction function issues
我定义了以下 n 元函数:
(define (- . l)
(cond ((null? l) 0)
(else (b- (car l) (apply - (cdr l))))))
它适用于两个参数,但现在它开始以一种奇怪的方式添加数字,我不明白为什么。
或者,如果只有一个参数,我会在该函数的不同版本中实施检查:
(define (- . l)
(cond ((null? (cdr l)) (b- (b* l 2) l))
(else (b- (car l) (apply - (cdr l))))))
当我改变第一个条件时,第二个根本不起作用。
输入应该类似于 (- 10 6 1)
我假设 b-
是一个二进制减法,并且您想模仿 Scheme 的常用减法,它是这样的函数:
- 没有参数,会报错,
- 带参数,改变参数的符号,
- 有多个参数时,从第一个参数中减去所有其他参数。
这是一个可能的解决方案(注意我已经调用函数 n-
):
(define (n- . l)
(define (aux l dec)
(if (null? l)
dec
(aux (cdr l) (b- dec (car l)))))
(cond ((null? l) (println "Error"))
((null? (cdr l)) (b- 0 (car l)))
(else (aux (cdr l) (car l)))))
(n-) ; => Error
(n- 3) ; => -3
(n- 10 6 1) ; => 3
(n- 11 4 8 2) ; => -3
辅助函数将列表第一个参数的所有数字减去第二个参数,定义为尾递归函数,因此可以迭代实现。
实现 -
的明智方法是使用 case-lambda
,以便可以分别处理一元、二元和可变参数情况:
(define -
(case-lambda
((a) (b- 0 a))
((a b) (b- a b))
((a b . rest) (apply - (b- a b) rest))))
现在,如果您没有 case-lambda
,那么您将有更多工作要做:
(define (- a . rest)
(if (null? rest)
(b- 0 a)
(let loop ((result a)
(rest rest))
(if (null? rest)
result
(loop (b- result (car rest)) (cdr rest))))))
此特殊情况一元调用取反;否则,它迭代,使用第一个参数作为初始结果,并且每次通过减法更新结果。
我定义了以下 n 元函数:
(define (- . l)
(cond ((null? l) 0)
(else (b- (car l) (apply - (cdr l))))))
它适用于两个参数,但现在它开始以一种奇怪的方式添加数字,我不明白为什么。
或者,如果只有一个参数,我会在该函数的不同版本中实施检查:
(define (- . l)
(cond ((null? (cdr l)) (b- (b* l 2) l))
(else (b- (car l) (apply - (cdr l))))))
当我改变第一个条件时,第二个根本不起作用。
输入应该类似于 (- 10 6 1)
我假设 b-
是一个二进制减法,并且您想模仿 Scheme 的常用减法,它是这样的函数:
- 没有参数,会报错,
- 带参数,改变参数的符号,
- 有多个参数时,从第一个参数中减去所有其他参数。
这是一个可能的解决方案(注意我已经调用函数 n-
):
(define (n- . l)
(define (aux l dec)
(if (null? l)
dec
(aux (cdr l) (b- dec (car l)))))
(cond ((null? l) (println "Error"))
((null? (cdr l)) (b- 0 (car l)))
(else (aux (cdr l) (car l)))))
(n-) ; => Error
(n- 3) ; => -3
(n- 10 6 1) ; => 3
(n- 11 4 8 2) ; => -3
辅助函数将列表第一个参数的所有数字减去第二个参数,定义为尾递归函数,因此可以迭代实现。
实现 -
的明智方法是使用 case-lambda
,以便可以分别处理一元、二元和可变参数情况:
(define -
(case-lambda
((a) (b- 0 a))
((a b) (b- a b))
((a b . rest) (apply - (b- a b) rest))))
现在,如果您没有 case-lambda
,那么您将有更多工作要做:
(define (- a . rest)
(if (null? rest)
(b- 0 a)
(let loop ((result a)
(rest rest))
(if (null? rest)
result
(loop (b- result (car rest)) (cdr rest))))))
此特殊情况一元调用取反;否则,它迭代,使用第一个参数作为初始结果,并且每次通过减法更新结果。