Domanda

La seguente procedura è valida sia in R6RS schema e 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)))

Ho testato sia per R6RS e racchetta e funziona correttamente, ma so solo che di sicuro per DrRacket.

La mia domanda è se si tratta di garantito che le espressioni di passo ((- x 1) e (cons x lst) in questo caso) saranno valutate in ordine. Se non è garantito, allora la mia procedura non è molto stabile.

Non ho visto nulla di specificare questo nelle norme sia per la lingua, ma sto chiedendo qui perché quando ho provato è stato evaulated in ordine.

È stato utile?

Soluzione

Si stanno generalmente non garantita da valutare in ordine, ma il risultato sarà comunque lo stesso. Questo è perché non ci sono effetti collaterali qui -. Il ciclo non cambia x o lst, semplicemente li rebinds a nuovi valori, in modo da l'ordine in cui vengono valutate le due espressioni passo è irrilevante

Per vedere questo, iniziare con una versione più pulita dall'aspetto del vostro codice:

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

tradursi in un-let nome:

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

e l'ulteriore traduce che per una funzione di supporto (che è ciò che un-let nome è in realtà):

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

Dovrebbe essere chiaro ormai che l'ordine di valutare le due espressioni nella chiamata loop ricorsiva non fargli fare qualcosa di diverso.

Infine, ricordiamo che nella valutazione Racket è garantito da sinistra a destra. Questo è importante quando ci sono effetti collaterali - Racket preferisce un comportamento prevedibile, mentre altri obiettano ad esso, sostenendo che questo porta le persone a codice che implicitamente si basa su questo. Un piccolo esempio comune che mostra la differenza è:

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

che a sua Racket è garantito per restituire un elenco della prima linea di lettura, e poi la seconda. Altre implementazioni potrebbero restituire le due linee in un ordine diverso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top