In the book The little schemer, we find this function that only supports lists with length smaller than or equal to 1:
(((lambda (mk-length) ; A.
(mk-length mk-length))
(lambda (mk-length)
(lambda (l)
(cond
((null? l ) 0)
(else (add1 ((mk-length eternity ) (cdr l))))))))
'(1))
I want to study step by step, and want to write the similar function that supports only lists of length smaller than or equal to 2.
Please, don't answer this question by offering code like:
(((lambda (mk-length) ; B.
(mk-length mk-length))
(lambda (mk-length)
(lambda (l)
(cond
((null? l) 0 )
(else (add1((mk-length mk-length) (cdr l))))))))
'(a b c d))
because this function supports any length.
And I already know how to write function like this:
(((lambda (mk-length) ; C.
(mk-length
(mk-length (mk-length eternity))))
(lambda (length)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))))
'(1 2)) ;;
to achieve my goal. But this code is more than one step away from the first snippet.
Maybe, I should not change:
(lambda (mk-length) ; D.
(mk-length mk-length)
TL;DR:
(mk-length A)
(inside thecond
form) calculates thelength
function that works for lists of length 0 and will use(A A)
to calculate thelength
function that will be used to work on the tail (i.e. the result of(cdr ...)
) of the argument list.Your first code snippet (
;A.
) works for lists of length 0 and 1 only. To make it work for 2 also, replacingwith
works.
(NB:
(mk-length eternity)
itself calculateslength≤0
, but the overall function becomeslength≤1
; this is what all the furtherlength≤i
comments refer to.)Looking closely at
we can see that the result of
(mk-length ...)
at;(2)
is used to process(cdr l)
, while theargument
tomk-length
at;(2)
will replacemk-length
in that call when processing the(cddr l)
.If
(mk-length eternity)
is used (as in your first code),(cdr l)
gets processed OK but((eternity eternity) (cddr l))
naturally fails.If
(mk-length (lambda (x) (mk-length eternity)))
is used,(cdr l)
gets processed OK and then((lambda (x) (mk-length eternity)) (lambda (x) (mk-length eternity))) = (mk-length eternity)
is used to process(cddr l)
which is also OK (so, length 2 is handled correctly), and then((eternity eternity) (cdddr l))
naturally fails (for lengths 3 and up).Thus to process the lists of up to three elements,
can be used:
As you correctly surmised, this is the interim step on the way to using
which turns, on the processing of the next element of the list into
and thus works for every list, whatever its length is.
And by eta-conversion this is just
(mk-length mk-length)
.