开发者

Scheme evaluation order standard

I've got a program I'm writing for a class to substitute the left-most occurrence of a variable with a new variable. (It actually allows you to provide an equivalence relation yourself, as well). The thing is, in Chez Scheme 8.2, this substitutes the right-most occurrence, if the left most is inside a list. We use a server running some version of scheme (I'm not sure which version), and on the server it substitutes, correctly, the left-most occurrence. Below is the code:

(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))))

This is called like so: (subst-leftmost 'x 'a '(d b c (a) b a) eq?) which should produce th开发者_开发百科e output (d b c (x) b a), and does on the server. In Chez scheme, however, it produces (d b c (a) b x). I think the difference is due to the line

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

evaluating the helper of the car and the helper of the cdr in a not-set order.

My question is this: Which version of scheme is following the standard, and how can I modify my code so that it works correctly in both versions?

(I've already talked to my professor about this. He's going to address the class about it on Monday, once he can think about it some, but I'm curious. I also already got the full points for the assignment, so don't worry about the ethics of helping me, in that regard.)


There isn't any, sorry. Here's the relevant legalese. Use LETs or LET* if you need to evaluate sub-expressions in a particular order.


Scheme guarantees no specific order (as Cirno has said). If your code has no side-effects, this doesn't matter.

However, your code is side-effecting (because of the set! to an outside variable), so, you have some choices:

  • Use Racket (which is committed to using left-to-right order, last time I talked to a Racket dev)
  • Structure your code to remove side-effects, so that your helper function doesn't change any variable or state outside it
  • Use appropriate lets to ensure the ordering you need (as Cirno suggested); in particular, change (cons (helper (car ls)) (helper (cdr ls))) to:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜