Question

La procédure suivante est valable dans les deux r6rs régime et 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)))

Je l'ai testé pour les deux r6rs et Racket et il fonctionne bien, mais je sais seulement que sûr pour DrRacket.

Ma question est si elle est garantie que les expressions de l'étape ((- x 1) et (cons x lst) dans ce cas) seront évalués en ordre. Si ce n'est pas garanti, ma procédure n'est pas très stable.

Je ne vois rien préciser cela dans les normes pour les deux langues, mais je demande ici parce que quand je l'ai testé était evaulated dans l'ordre.

Était-ce utile?

La solution

Ils sont généralement pas garantie à évaluer dans l'ordre, mais le résultat sera toujours le même. En effet, il n'y a pas d'effets secondaires ici -. La boucle ne change pas x ou lst, il suffit de les nouvelles valeurs de lie de nouveau, de sorte que l'ordre dans lequel les deux expressions sont évaluées étape est hors de propos

Pour voir cela, commencer par une version plus propre à la recherche de votre code:

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

se traduire par un nom-let:

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

et plus que traduire à une fonction d'assistance (qui est ce qu'un nom-let est vraiment):

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

Il doit être clair maintenant que l'ordre d'évaluer les deux expressions dans l'appel loop récursive ne fait pas faire quelque chose de différent.

Enfin, notez que dans l'évaluation Racket garantie à gauche à droite. Cela est important quand il y a des effets secondaires - Racket Préfère un comportement prévisible, alors que d'autres s'y opposent, affirmant que cela conduit les gens à code qui repose implicitement sur ce point. Un petit exemple courant qui montre la différence est:

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

qui Racket est garanti pour retourner une liste de la première ligne lue, puis la deuxième. D'autres implémentations pourraient renvoyer les deux lignes dans un ordre différent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top