4

次の手順は、スキームr6rsとRacketの両方で有効です。

;; create a list of all the numbers from 1 to n
(define (make-nums n)
  (do [(x n (- x 1)) (lst (list) (cons x lst))]
    ((= x 0)
     lst)))

私はr6rsとRacketの両方でテストしましたが、正しく動作しますが、DrRacketで確実に動作することしかわかりません。

私の質問は、ステップ式(この場合は)が順番に評価されることが保証されているかどうかです。保証されていない場合、私の手順はあまり安定していません。(- x 1)(cons x lst)

どちらの言語の標準でもこれを指定するものは見当たりませんでしたが、テストしたときに順番に評価されたため、ここで質問しています。

4

1 に答える 1

10

通常、順番に評価されるとは限りませんが、結果は同じです。これは、ここには副作用がないためです。ループは変更されないxlst、新しい値に再バインドされるだけなので、2つのステップ式が評価される順序は関係ありません。

これを確認するには、コードの見栄えの良いバージョンから始めます。

(define (make-nums n)
  (do ([x n (- x 1)] [lst null (cons x lst)])
      [(zero? x) lst]))

名前付きに翻訳- let

(define (make-nums n)
  (let loop ([x n] [lst null])
    (if (zero? x)
      lst
      (loop (- x 1) (cons x lst)))))

さらに、それをヘルパー関数(名前付きのlet実際の関数)に変換します。

(define (make-nums n)
  (define (loop x lst)
    (if (zero? x)
      lst
      (loop (- x 1) (cons x lst))))
  (loop n null))

再帰loop呼び出しで2つの式を評価する順序によって、何も変わらないことは明らかです。

最後に、Racketの評価では、左から右への評価が保証されていることに注意してください。これは副作用がある場合に重要です-ラケットは予測可能な動作を好みますが、他の人はそれに反対し、これが暗黙のうちにこれに依存するコードに人々を導くと主張します。違いを示す一般的な小さな例は次のとおりです。

(list (read-line) (read-line))

これは、Racketで、読み取られた最初の行のリストを返し、次に2番目の行のリストを返すことが保証されています。他の実装では、2行が異なる順序で返される場合があります。

于 2010-09-15T03:23:17.417 に答える