racket
Rekursion
Sök…
Använd definiera
#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
Med hjälp av 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
Det är möjligt att skriva ömsesidigt rekursiva funktioner med 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)
Med hjälp av ett namngivet låt
En normal let
binder varje värde till dess motsvarande identifierare, innan kroppen körs. Med ett "namngivet let
" kan kroppen sedan rekursivt utföras på nytt, vilket ger ett nytt värde för varje identifierare.
#lang racket
(let sum-of-list ([l '(1 2 3)])
(if (null? l)
0
(+ (car l) (sum-of-list (cdr l)))))
;; => 15
Det är vanligt att använda rec
som namn på let, vilket ger:
#lang racket
(let rec ([l '(1 2 3 4 5)])
(if (null? l)
0
(+ (car l) (rec (cdr l)))))
;; => 15
Använda 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
Detta liknar att define
, men sum-of-list
listidentifieraren är inte synlig utanför rec
formuläret.
För att undvika att använda ett uttryckligt λ
, är det möjligt att ersätta sum-of-list
med (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
Använda högre ordning i stället för rekursion
Det är vanligt att använda högre ordning i stället för rekursion, om det finns en högre ordning som uttrycker rätt rekursionsmönster. I vårt fall kan sum-of-numbers
definieras med hjälp av foldl
:
#lang racket
(define (sum-of-numbers l)
(foldl + 0 l))
(sum-of-numbers '(1 2 3 4 5)) ;; => 15
Det är möjligt att ringa foldl
direkt på listan:
#lang racket
(foldl + 0 '(1 2 3 4 5)) ;; => 15