2016-11-28 9 views
0

У меня есть следующие п-арной функции я определил:Схема - п-арной функции вычитания вопросы

(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)))))) 

Это второй один не работает вообще, когда я изменить первое условие. Input должно быть что-то вроде (- 10 6 1)

+1

Помните, что вы не можете просто изменить порядок выполнения надстроек. Ваша функция вычисляет '10 - (6 - 1)' -> '5' вместо' (10 - 6) - 1' -> '3'. – jkiiski

+1

Или, иначе говоря, '(- a b c)' is '(- a (+ b c))', а не '(- a (- b c))'. (И ваша вторая версия пытается mulitply и вычесть список, единственный аргумент - '(car l)'.) – molbdnilo

ответ

2

Я предполагаю, что b- является двоичным вычитанием, и что вы хотите, чтобы имитировать обычное вычитание по схеме, которая является функцией таким образом, что:

  1. без аргументов, дает ошибка,
  2. с аргументом, изменяет знак аргумента,
  3. с более чем одним аргументом, вычитает из первого все остальные.

Вот решение possibile (обратите внимание, что я назвал функцию 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 

Вспомогательная функция вычитает все номера из списка первого аргумента второго аргумента, и это определяемый как хвостовая рекурсивная функция, так что он может быть реализован итеративным способом.

+0

А, спасибо Ренцо! – TacoB0t

2

Здравомыслящий способ реализации - является использование case-lambda, так что унарные, бинарные и VARIADIC случаи могут быть обработаны отдельно:

(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)))))) 

Этот специальный случайный унарный вызов для отрицания; в противном случае он выполняет итерацию, используя первый аргумент в качестве исходного результата и каждый раз обновляет результат путем вычитания.