我尝试在Scheme中实现扩展的Euler算法,并找到了正确的结果,但是我的主要目标是将解决方案作为一对。但是我不明白为什么我的夫妻前面会有mcons
标记。
这是我的功能和输出
(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))))))
; > (ax+by=1 17 13)
; (mcons -3 4)
我需要一个建议以(-3 4)
的形式获得答案。
答案 0 :(得分:2)
这与DrRacket中使用的语言或打印设置有关。只是它的可视化方式。如果您问我XI
是什么,而我回答mcons
是错误的答案吗?
通常,如果您在球拍语言中使用rnrs库,则会看到cons
,因为它是一对标准方案,在该模式下命名为#lang racket
,但可视化与例如不同。 operator<<()
答案 1 :(得分:1)
(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单元格的最后一个元素不是'()
。
列表是任何约束单元链,最后一个元素为nil
。
如果您的代码执行(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
的最后一个函数调用中,解释器/编译器“知道”内部函数的含义,而不是外部函数的含义(否则外部函数将再次调用自身)并在无限循环中再次传递给定的参数)。这是可能的,因为内部功能名称绑定“遮盖了”外部功能名称绑定。
但是,我认为这真的很糟糕,因为人类读者可能会对内部函数和外部函数之间的相同名称感到非常困惑。 尽管如此,我发现找到一种有趣的方法是找到一种方法,不修改现有代码,而只是添加一些东西以使它正常工作,甚至使用预期的旧名称-这样结果就恰好是期望的结果。
但是,我给出的第一个解决方案肯定是更好的-不会误解代码并弄乱事情-可以直接构建结果列表。