Scheme 为什么我的配对输出中会有mcons符号?

Scheme 为什么我的配对输出中会有mcons符号?,scheme,racket,Scheme,Racket,我尝试在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)

我尝试在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)
我需要一个建议,以
(-34)
的形式得到答案

您的“问题”是函数返回的cons单元格的最后一个元素不是
”()
。 列表是任何cons单元格链,最后一个元素为
nil

如果代码执行
(cons 3.4)
,则返回
(3.4)
。或者用你的符号(它不是球拍,不是吗?或者球拍的一个子刻度?
(mcons 3 4)
)。 要使它成为一个普通的列表,它必须变成
(cons 3(cons 4’())
,这与
(list 3 4)
列表
在其最后一个
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) '()))))))
超级惰性解决方案

或者,假设您非常懒惰,并且您看到您的旧函数实际上做了它应该做的事情—只需将输出格式从pair更改为list

使用此函数,您可以将该对转换为列表:

(define (pair->list p)
  (list (car p) (cdr p))) ; just list the components of pair
然后,您可以使用旧函数(未经修改),然后使用transformer函数,并将其包装为函数定义,即使使用相同的名称(然而,这对可读性非常不利!-然而,有趣的是,这在Racket中有效…)

最后一个版本值得注意的是,在
ax+by=1
的最后一个函数调用中,解释器/编译器“知道”内部函数的含义,而不是外部函数(否则外部函数将在无休止的循环中一次又一次地调用自身)。这是可能的,因为内部函数名绑定“隐藏”了外部函数名绑定

但是,我认为这是一种很差的文体,因为人类读者可能会对内、外功能的同一名称感到困惑。 尽管如此,我发现找到一种不修改现有代码的方法是很有趣的,只需添加一些东西就可以让它工作,甚至使用预期的旧名称——这样结果就是所需的结果


但我给出的第一个解决方案肯定更好——不可能误解代码和混淆东西——并直接构建结果列表。

这与DrRacket中使用的语言或打印设置有关。这只是它的可视化方式。如果你问我什么是
5+6
,我回答
XI
,答案是回答错了吗


通常,如果您在racket语言中使用rnrs库,您会看到
mcons
,因为它是标准方案对,在该模式下命名为
cons
,但其可视化方式与例如
#lang racket
mcons
不同。例如,当源文件顶部有
#lang r5rs
时,我们会得到它n个常规方案cons单元是可变的。即set car!和set cdr!可用于操纵它们。racket将此类cons称为“mcons”,m表示“可变”。
(define (pair->list p)
  (list (car p) (cdr p))) ; just list the components of pair
(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!