方案——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 的常用减法,它是这样的函数:

  1. 没有参数,会报错,
  2. 带参数,改变参数的符号,
  3. 有多个参数时,从第一个参数中减去所有其他参数。

这是一个可能的解决方案(注意我已经调用函数 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))))))

此特殊情况一元调用取反;否则,它迭代,使用第一个参数作为初始结果,并且每次通过减法更新结果。