(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-cell。
列表是任何最后一个元素为 nil 的 cons-cells 链。
如果您的代码执行(cons 3 4),则返回(3 . 4)。或者在你的符号中(它不是 Racket,不是吗?或者 Racket 的子方言?(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 的最后一个函数调用中,解释器/编译器“知道”内部函数是指内部函数而不是外部函数(否则外部函数会一次又一次地调用自身在无限循环中传递给定的参数)。这是可能的,因为内部函数名绑定“遮蔽”了外部函数名绑定。
但是,我认为它的风格非常糟糕,因为人类读者可能会对内部函数和外部函数之间的相同名称感到非常困惑。
尽管如此,我发现找到一种不修改现有代码的方法很有趣,只需添加一些东西以使事情正常工作,甚至使用预期的旧名称 - 这样结果正是预期的结果。
但绝对是我给出的第一个解决方案更好 - 不可能误解代码和混淆事物 - 并且直接构建结果列表。