【问题标题】:Scheme evaluation order standard方案评审顺序标准
【发布时间】:2011-04-02 07:46:49
【问题描述】:

我正在为一个类编写一个程序,用一个新变量替换最左边出现的变量。 (它实际上也允许您自己提供等价关系)。问题是,在 Chez Scheme 8.2 中,如果最左边的出现在列表中,这会替换最右边的出现。我们使用运行某个版本的方案的服务器(我不确定哪个版本),并且在服务器上它正确地替换了最左边的出现。下面是代码:

(define subst-leftmost
  (lambda (new old ls proc)
    (let ([keep-going? #t])
      (letrec ([helper
         (lambda (ls)
           (cond [(null? ls) ls]
             [(or (pair? (car ls)) (null? (car ls)))
              (cons (helper (car ls)) (helper (cdr ls)))]
             [(and keep-going? (proc old (car ls)))
              (set! keep-going? #f) (cons new (cdr ls))]
             [else (cons (car ls) (helper (cdr ls)))]))]) (helper ls))))

这样调用: (subst-leftmost 'x 'a '(d b c (a) b a) eq?) 应该产生输出 (d b c (x) b a),并在服务器上执行。然而,在 Chez 方案中,它产生 (d b c (a) b x)。我认为差异是由于线

[(or (pair? (car ls)) (null? (car ls)))
 (cons (helper (car ls)) (helper (cdr ls)))]

以未设置的顺序评估汽车的助手和 cdr 的助手。

我的问题是:哪个版本的方案遵循标准,如何修改我的代码以使其在两个版本中都能正常工作?

(我已经和我的教授谈过了。他将在周一向全班讲这件事,一旦他可以考虑一下,但我很好奇。我也已经得到了作业的满分,所以在这方面不要担心帮助我的道德。)

【问题讨论】:

    标签: scheme


    【解决方案1】:

    没有,抱歉。 Here's the relevant legalese. 如果您需要按特定顺序计算子表达式,请使用 LET 或 LET*。

    【讨论】:

    • 我尝试了 LET,但我对每个部分都使用了 LET,而不仅仅是一个。所以我只是将评估顺序问题移到了 let 内部。一旦我只在汽车部分使用了一个 let ,它就完美地工作了。谢谢。
    • @Colin: let* 保证给定变量的从左到右绑定。仅供日后参考。 :-)
    • @Chris:这是有道理的,它必须这样做。谢谢!
    【解决方案2】:

    Scheme 不保证特定的顺序(正如 Cirno 所说)。如果你的代码没有副作用,这没关系。

    但是,您的代码 会产生副作用(因为 set! 是外部变量),因此,您有一些选择:

    • 使用 Racket(承诺使用从左到右的顺序,上次我与 Racket 开发人员交谈时)
    • 构建您的代码以消除副作用,以便您的 helper 函数不会更改其外部的任何变量或状态
    • 使用适当的lets 来确保您需要的顺序(如 Cirno 建议的那样);特别是将(cons (helper (car ls)) (helper (cdr ls))) 更改为:

      (let ((depth-first (helper (car ls))))
        (cons depth-first (helper (cdr ls))))
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 2016-02-29
      • 2013-11-25
      相关资源
      最近更新 更多