【问题标题】:Why am I getting mcons notation in my pair output?为什么我的 pair 输出中出现 mcons 符号?
【发布时间】:2018-10-28 00:59:41
【问题描述】:

我尝试在 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) 的形式获得答案的建议。

【问题讨论】:

    标签: scheme racket


    【解决方案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-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 的最后一个函数调用中,解释器/编译器“知道”内部函数是指内部函数而不是外部函数(否则外部函数会一次又一次地调用自身在无限循环中传递给定的参数)。这是可能的,因为内部函数名绑定“遮蔽”了外部函数名绑定。

    但是,我认为它的风格非常糟糕,因为人类读者可能会对内部函数和外部函数之间的相同名称感到非常困惑。 尽管如此,我发现找到一种不修改现有代码的方法很有趣,只需添加一些东西以使事情正常工作,甚至使用预期的旧名称 - 这样结果正是预期的结果。

    但绝对是我给出的第一个解决方案更好 - 不可能误解代码和混淆事物 - 并且直接构建结果列表。

    【讨论】:

    • mcons 是当有例如#lang r5rs 在源文件的顶部。在常规 Scheme 中,单元格是可变的。即定车!和设置-cdr!可以用来操纵它们。球拍称这样的conses为“mcons”,“m”表示“可变”。
    【解决方案2】:

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

    通常,如果您在球拍语言中使用 rnrs 库,您会看到 mcons,因为它是标准方案的对,在该模式下名为 cons,但可视化与例如不同。 #lang racket

    【讨论】:

      猜你喜欢
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 2021-02-26
      • 2018-02-26
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 2012-02-12
      相关资源
      最近更新 更多