racket
Рекурсия
Поиск…
Использование определения
#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
Использование 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
Можно написать взаимно-рекурсивные функции с 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)
Использование имени let
Нормальная форма let
связывает каждое значение с соответствующим идентификатором перед выполнением тела. С помощью «named let
» тело может быть рекурсивно повторно выполнено, передавая новое значение для каждого идентификатора.
#lang racket
(let sum-of-list ([l '(1 2 3)])
(if (null? l)
0
(+ (car l) (sum-of-list (cdr l)))))
;; => 15
Обычно используется rec
как имя для let, которое дает:
#lang racket
(let rec ([l '(1 2 3 4 5)])
(if (null? l)
0
(+ (car l) (rec (cdr l)))))
;; => 15
Использование 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
Это похоже на define
, но идентификатор sum-of-list
не отображается вне rec
.
Чтобы избежать использования явного λ
, можно заменить sum-of-list
(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
Использование функций более высокого порядка вместо рекурсии
Общепринятой практикой является использование функций более высокого порядка вместо рекурсии, если есть функция более высокого порядка, которая выражает правильный рекурсивный рисунок. В нашем случае sum-of-numbers
может быть определена с помощью foldl
:
#lang racket
(define (sum-of-numbers l)
(foldl + 0 l))
(sum-of-numbers '(1 2 3 4 5)) ;; => 15
Вы можете вызвать foldl
непосредственно в списке:
#lang racket
(foldl + 0 '(1 2 3 4 5)) ;; => 15