Lo stile comune per Lisp commenti è
- Quattro punti e virgola per il commento su un intero sottosezione di un file.
- Tre punti e virgola per l'introduzione di una singola procedura.
- Due punti e virgola per una descrizione della definizione di espressione/procedura nella riga seguente.
- Un punto e virgola per un commento di fine riga.
Procedura Commenti Panoramica dovrebbero probabilmente seguire lo stile di RnRS documens, per così basta aggiungere commenti alla procedura così come sono, sarebbe simile
;;; Procedure: display-n NUM ...
;; Output each argument to the screen in the order they are provided.
(define
display-n (lambda nums
(letrec ((display-n-inner (lambda (nums)
(display (car nums))
(if (not (equal? (cdr nums) '()))
(display-n-inner (cdr nums))))))
(display-n-inner nums))))
N.B. Non uso tre punti e virgola per l'intera descrizione della procedura, poiché svuota il paragrafo di riempimento in Emacs.
Ora, riguardo al codice, vorrei abbandonare l'intera definizione di variabile-come-una-cosa lambda.Sì, ho capito che questo è il modo "più puro" per definire una funzione, e rende la coerenza con le procedure definitive i risultati di LET e altre procedure, ma c'è una ragione per lo zucchero sintattico, ed è per rendere le cose più leggibile. Lo stesso vale per il LETREC: basta usare un DEFINE interno, che è la stessa cosa ma più leggibile.
Non è un affare enorme che il parametro del display-N-INTERNO si chiama NUMS, dal momento che il procedimento così breve e DISPLAY-N porge solo i suoi NUMS dritto ad esso comunque. "DISPLAY-N-INNER" è una specie di nome zoppo, però. Darei qualcosa con un significato più semantico, o dargli un nome semplice come "ITER" o "LOOP".
Ora sulla logica della procedura. Innanzitutto, (equal? (cdr nums) '())
è sciocco, ed è meglio come (null? (cdr nums))
. In realtà, quando si opera su un intero elenco, è meglio fare in modo che il caso base verifichi se la lista stessa, e non il suo CDR, è vuota. In questo modo la procedura non verrà erroneamente se non si passa nessun argomento (a meno che non si voglia farlo, ma penso che abbia più senso per DISPLAY-N a do nulla se non ottiene nulla). Inoltre, è necessario verificare se fermare la procedura, non è se continuare:
(define (display-n . nums)
(define (iter nums)
(if (null? nums)
#t ; It doesn't matter what it returns.
(begin (display (car nums))
(iter (cdr nums)))))
(iter nums))
Ma per tutto questo, direi che la procedura stessa non è il modo migliore per realizzare il compito che fa, dal momento che è troppo interessato ai dettagli di attraversare una lista. Invece dovresti usare il metodo FOR-EACH più astratto per fare il lavoro.
(define (display-n . nums)
(for-each display nums))
questo modo, invece di un lettore della procedura di ottenere impantanato nei dettagli di automobili e CDR, si può solo capire che la for-each mostrerà ogni elemento di NUMS.
+1, tutto ciò è un buon consiglio (specialmente la parte sullo zucchero sintattico). Inoltre, tbh in realtà non sapevo di 'null?' - quindi è utile. Per quanto mi riguarda, mi rendo conto che è il modo migliore per affrontare effettivamente questo particolare problema, ma il mio frammento di codice sarebbe stato troppo banale :) – Cam
Come un'altra forma intermedia, perché usare la procedura interna? È possibile rendere il ricorsivo esterno senza perdita di incapsulamento. – Svante
@Svante: È perché il 'nums 'esterno è una lista composta da tutti gli argomenti forniti alla funzione. Chiamando la procedura esterna in modo ricorsivo si fornisce solo un parametro, gli argomenti sotto forma di elenco. Il problema è che 'display-n' si aspetta in realtà più argomenti - non un argomento che è una lista, quindi non funzionerebbe. Detto questo, il tuo suggerimento sarebbe possibile usando 'apply' - eccetto che non sono sicuro di quanto sia efficace' apply', così che comunque potrebbe non essere una buona soluzione. – Cam