Рекурсивная функция не работает как запланировано

Я пишу функцию в схеме, которая должна принимать два целых числа, X и Y, а затем рекурсивно добавить X/Y + (X-1)/(Y-1) + ...пока одно из чисел не достигнет 0.

Например, возьмите 4 и 3:

4/3 + 3/2 + 2/1 = 29/6

Вот моя функция, которая не работает правильно:

(define changingFractions (lambda (X Y)
    (cond 
        ( ((> X 0) and (> Y 0)) (+ (/ X Y) (changingFunctions((- X 1) (- Y 1)))))
        ( ((= X 0) or (= Y 0)) 0)
    )
))

РЕДАКТИРОВАТЬ: я изменил свой код, чтобы исправить проблему, указанную в комментариях, а также изменить местоположение or а также and,

(define changingFractions (lambda (X Y)
    (cond 
        ( (and (> X 0) (> Y 0)) (+ (/ X Y) (changingFunctions (- X 1) (- Y 1) )))
        ( (or (= X 0) (= Y 0)) 0)
    )
))

К сожалению, я все еще получаю ошибку.

2 ответа

Решение

Пара проблем там:

  • Вы должны определить функцию с синтаксисом (define (func-name arg1 arg2 ...) func-body)вместо присвоения лямбда-функции переменной.
  • and а также or используются как функции, имея их в качестве первого элемента в форме ((and x y) скорее, чем (x and y)). Не имея их между аргументами.
  • У вас есть дополнительный набор символов вокруг параметров функции для рекурсивного вызова, и вы написали changingFunctions когда имя changingFractions,
  • Не ошибка, но не ставьте закрывающие скобки на собственной линии.
  • Соглашение об именах в Lisps - использовать тире, а не camelcase (changing-fractions скорее, чем changingFractions).

С исправленными:

(define (changing-fractions x y)
  (cond 
   ((and (> x 0) (> y 0)) (+ (/ x y) (changing-fractions (- x 1) (- y 1))))
   ((or (= x 0) (= y 0)) 0)))

Но вы могли бы изменить cond для if чтобы было понятнее:

(define (changing-fractions x y)
  (if (and (> x 0) (> y 0))
      (+ (/ x y) (changing-fractions (- x 1) (- y 1)))
      0))

Мне лично нравится эта реализация. Он имеет правильный хвостовой вызов в отличие от других ответов, представленных здесь.

(define (changing-fractions x y (z 0))
  (cond ((zero? x) z)
        ((zero? y) z)
        (else (changing-fractions (sub1 x) (sub1 y) (+ z (/ x y))))))

(changing-fractions 4 3) ; => 4 5/6

Хитрость необязательна z параметр по умолчанию 0, Используя этот аккумулятор, мы можем итеративно наращивать дробную сумму каждый раз changing-fractions. рекурсивно Сравните это с дополнительными кадрами стека, которые добавляются для каждой рекурсии в ответе @jkliski.

; changing-fractions not in tail position...
(+ (/ x y) (changing-fractions (- x 1) (- y 1)))
Другие вопросы по тегам