racket
ricorsione
Ricerca…
Utilizzando define
#lang racket
(define (sum-of-list l)
(if (null? l)
0
(+ (car l)
(sum-of-list (cdr l)))))
(sum-of-list '(1 2 3 4 5)) ;; => 15
Usando il let-rec
#lang racket
(letrec ([sum-of-list (λ (l)
(if (null? l)
0
(+ (car l) (sum-of-list (cdr l)))))])
(sum-of-list '(1 2 3 4 5)))
;; => 15
È possibile scrivere funzioni reciprocamente ricorsive con letrec
:
#lang racket
(letrec ([even? (λ (n) (if (= n 0) #t (odd? (sub1 n))))]
[odd? (λ (n) (if (= n 0) #f (even? (sub1 n))))])
(list (even? 3)
(odd? 5)))
;; => '(#f #t)
Usando un let chiamato
Una forma let
normale lega ogni valore al suo identificatore corrispondente, prima di eseguire il corpo. Con un "named let
", il corpo può essere ricorsivamente ricorsivo, passando un nuovo valore per ogni identificatore.
#lang racket
(let sum-of-list ([l '(1 2 3)])
(if (null? l)
0
(+ (car l) (sum-of-list (cdr l)))))
;; => 15
È comune usare rec
come il nome per il let, che dà:
#lang racket
(let rec ([l '(1 2 3 4 5)])
(if (null? l)
0
(+ (car l) (rec (cdr l)))))
;; => 15
Utilizzando rec
#lang racket
(require mzlib/etc)
((rec sum-of-list
(λ (l)
(if (null? l)
0
(+ (car l) (sum-of-list (cdr l))))))
'(1 2 3 4 5))
;; => 15
;; Outside of the rec form, sum-of-list gives an error:
;; sum-of-list: undefined;
;; cannot reference an identifier before its definition
Questo è simile a define
, ma l'identificatore della sum-of-list
non è visibile al di fuori del form rec
.
Per evitare di usare un λ
esplicito, è possibile sostituire sum-of-list
con (sum-of-list args ...)
:
#lang racket
(require mzlib/etc)
((rec (sum-of-list l)
(if (null? l)
0
(+ (car l) (sum-of-list (cdr l)))))
'(1 2 3 4 5))
;; => 15
Utilizzo di funzioni di ordine superiore anziché ricorsione
È prassi comune utilizzare funzioni di ordine superiore invece di ricorsione, se esiste una funzione di ordine superiore che esprime il modello di ricorsione corretto. Nel nostro caso, la sum-of-numbers
può essere definita usando foldl
:
#lang racket
(define (sum-of-numbers l)
(foldl + 0 l))
(sum-of-numbers '(1 2 3 4 5)) ;; => 15
È possibile chiamare foldl
direttamente nell'elenco:
#lang racket
(foldl + 0 '(1 2 3 4 5)) ;; => 15