Функция длины в "Закаленном интриганке"
Я читал Seasoned Schemer, и я столкнулся с этим определением функции длины
(define length
(let ((h (lambda (l) 0)))
(set! h (L (lambda (arg) (h arg))))
h))
Позже они говорят:
Какое значение (L (лямбда (arg) (h arg)))? Это функция
(lambda (l)
(cond ((null? l) 0)
(else (add1 ((lambda (arg) (h arg)) (cdr l))))))
Я не думаю, что я понимаю это полностью. Я предполагаю, что мы должны сами определить L как упражнение. Я написал определение L в определении длины, используя letrec. Вот что я написал:
(define length
(let ((h (lambda (l) 0)))
(letrec ((L
(lambda (f)
(letrec ((LR
(lambda (l)
(cond ((null? l) 0)
(else
(+ 1 (LR (cdr l))))))))
LR))))
(set! h (L (lambda (arg) (h arg))))
h)))
Итак, L принимает функцию в качестве аргумента и возвращает в качестве значения другую функцию, которая принимает список в качестве аргумента и выполняет рекурсию по списку. Я прав или безнадежно неправ в своей интерпретации? В любом случае определение работает
(length (list 1 2 3 4)) => 4
1 ответ
В "Закаленном интриганке" length
изначально определяется так:
(define length
(let ((h (lambda (l) 0)))
(set! h (lambda (l)
(if (null? l)
0
(add1 (h (cdr l))))))
h))
Позже в книге предыдущий результат обобщается и length
переопределен с точки зрения Y!
(аппликативный порядок, императивный комбинатор Y) вот так:
(define Y!
(lambda (L)
(let ((h (lambda (l) 0)))
(set! h (L (lambda (arg) (h arg))))
h)))
(define L
(lambda (length)
(lambda (l)
(if (null? l)
0
(add1 (length (cdr l)))))))
(define length (Y! L))
Первое определение length
показанный в вопросе является лишь промежуточным этапом - с L
Процедура точно так же, как определено выше, вы не должны переопределять ее. Цель этой части главы - получить второе определение, показанное в моем ответе.