(define ax+by=1
(lambda (a b)
(if (= a 0)
(list 0 1)
(let ((pair (ax+by=1 (remainder b a) a)))
(cons (- (cadr pair)
(* (quotient b a) (car pair)))
(list (car pair)))))))
; > (ax+by=1 17 13)
; '(-3 4)
Ваша "проблема" заключалась в том, что ваша функция возвращала cons-ячейку, последний элемент которой НЕ '()
.
Список - это любая цепочка cons-ячеек с последним элементом как nil
.
Если ваш код (cons 3 4)
, он возвращает (3 . 4)
. Или в вашей записи (это не Ракетка, не так ли? Или субдиалект Ракетки? (mcons 3 4)
).
Чтобы сделать его обычным списком, он должен стать (cons 3 (cons 4 '()))
, который точно такой же, как (list 3 4)
. list
принимает аргументы и помещает их в '()
в своей последней cons
ячейке.
(define ax+by=1
(lambda (a b)
(if (= a 0)
(cons 0 (cons 1 '()))
(let ((pair (ax+by=1 (remainder b a) a)))
(cons (- (cadr pair)
(* (quotient b a) (car pair)))
(cons (car pair) '()))))))
Супер ленивое решение
Или, скажем, вы супер ленивый, и вы видите, что ваша старая функция действительно делает то, что должна - только формат вывода должен быть изменен от пары к списку.
С помощью этой функции вы можете преобразовать пару в список:
(define (pair->list p)
(list (car p) (cdr p))) ; just list the components of pair
Затем вы можете взять свою старую функцию - без изменений - затем функцию преобразователя и обернуть вокруг нее определение функции - даже с тем же именем (однако, это действительно ПЛОХО для читабельности! - однако, интересно, что это работает в Racket ...).
(define ax+by=1
(lambda (a b)
;; your old function verbatim as inner `ax+by=1`:
(define ax+by=1
(lambda (a b)
(if (= a 0)
(cons 0 1)
(let ((pair (ax+by=1 (remainder b a) a)))
(cons (- (cdr pair)
(* (quotient b a) (car pair)))
(car pair))))))
;; the transformer function verbatim:
(define (pair->list p)
(list (car p) (cdr p)))
;; call both inner functions in combination!
(pair->list (ax+by=1 a b))))
;; `pair->list` transforms your answer into the correct list form!
Примечательно, что в этой последней версии в последнем вызове функции ax+by=1
интерпретатор / компилятор «знает», что подразумевается внутренняя функция, а не внешняя функция (иначе внешняя функция будет вызывать себя снова и снова передача заданных аргументов в бесконечный цикл). Это возможно, потому что внутренняя привязка имени функции «затеняет» внешнюю привязку имени функции.
Однако я бы посчитал это действительно плохим стилем, потому что читатель-человек может очень запутаться с одинаковым именем между внутренней и внешней функцией.
Тем не менее, мне было интересно найти способ не изменять существующий код и просто добавлять что-то, чтобы заставить его работать, и даже использовать намеченное старое имя - так, чтобы результат был точно желаемым результатом.
Но, безусловно, первые решения, которые я дал, лучше - нет возможности неправильно понять код и запутать вещи - и напрямую составить список результатов.