スキーム/ラケット:評価のループ順序を行います
-
02-10-2019 - |
質問
次の手順は、スキームR6Rとラケットの両方で有効です。
;; 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)))
R6Rとラケットの両方についてテストしましたが、適切に機能しますが、Drracketについては確実にしか知っていません。
私の質問はそれがあるかどうかです 保証されています ステップ表現((- x 1)
と (cons x lst)
この場合、)は順番に評価されます。保証されていない場合、私の手順はあまり安定していません。
どちらの言語の標準でこれを指定しているものは何も見ませんでしたが、テストしたときに順番に回避されたので、ここで尋ねています。
解決
それらは一般に順番に評価されることを保証されていませんが、結果は依然として同じです。これは、ここに副作用がないためです - ループは変更されません x
また lst
, 、それはそれらを新しい値に縮小するだけなので、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))
再帰の2つの式を評価する順序が今では明らかであるはずです loop
コールはそれが違うことをさせません。
最後に、ラケット評価では注意してください は 左から右に保証されています。これは、副作用がある場合に重要です。ラケットは予測可能な動作を好みますが、他の人はそれに反対し、これにより人々がこれに暗黙的に依存するようにコードするようになります。違いを示す一般的な小さな例は、次のとおりです。
(list (read-line) (read-line))
Racketでは、最初の行のリストを返すことが保証されており、2番目の行のリストを返します。他の実装では、2行を異なる順序で返す場合があります。