Little Schemer: why wrap (mk-length mk-length) into a function? - recursion

In The Little Schemer book, in Chapter 9, while building a length function for arbitrary long input, the following is suggested (on pages 170-171), that in the following code snippet (from page 168 itself):
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l)))))))
(mk-length mk-length))))
the part (mk-length mk-length), will never return and will be infinitely applying itself to itself:
Because we just keep applying mk-length to itself again and again and again...
and
But now that we have extracted (mk-length mk-length) from the function that makes length it does not return a function anymore.
Now, to cure this the book suggest:
Turn the application of mk-length to itself in our last correct version of length into a function.
Like, so:
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(cond
((null? l) 0 )
(else
(add1 (length (cdr l)))))))
(lambda (x)
((mk-length mk-length) x)))))
What I get puzzled by is:
If (mk-length mk-length)
does not return a function
how we can apply the result of (mk-length mk-length) to something, as if it is a function?
(lambda (x)
((mk-length mk-length) x))
How wrapping (mk-length mk-length) into a function solves the 'never returning' (i.e. infinite recursion) problem? My understanding is, that in:
(lambda (x)
((mk-length mk-length) x))
x will just be passed to infinitely recursive function, which never returns.

You probably copied the wrong code snippet, the one before that which you actually talk about. The first code you've shown is totally fine. What loops is, rather, this one:
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(mk-length mk-length)))) ; (3)
This is already answered here: the application (1) triggers the application (2) which triggers the application (3) right away, which is equivalent to (1)! Thus, the looping.
Wrapping it in a lambda (aka eta-expansion) delays the application (3) until the call to the constructed length is made in (4), and that's fully OK (you copied this with some typos as well):
((lambda (mk-length)
(mk-length mk-length)) ; (1)
(lambda (mk-length) ; (5)
((lambda (length) ; (2)
(lambda (l)
(cond
((null? l) 0)
(else (add1 (length (cdr l))))))) ; (4)
(lambda (x) ; (3)
(mk-length mk-length) x))))
(3) is a lambda expression now, not an application. Evaluating this lambda expression produces an anonymous function. This lambda function will perform the application (mk-length mk-length) later, when length is called.
(a longer explanation:)
(3) just returns the lambda function right away which gets bound to length, and (lambda (l) ...) is happily returned such that when that (lambda (l) ...) will be applied to some list, possibly causing this length1 to be called in (4), only then the application (mk-length mk-length) inside the lambda (3) will actually be performed — giving us the new (lambda (l) ...) anonymous function eventually, which will get applied to the (cdr l) there.
1length is (lambda (x) ((mk-length mk-length) x)) which means that (length (cdr l)) is the same as ((mk-length mk-length) (cdr l)) (with mk-length bound to the whole lambda-expression (5)), and eventually, ((lambda (l) ...) (cdr l)).
nina

This call
(mk-length mk-length)
will call mk-length only once.
If mk-length happens to call it-self, then the body of mk-length will
be evaluated again — but mk-length doesn't always call itself.
As to why — notice that no function in your expression has been named using define. All function expressions use lambda which introduce an anonymous function.
The example shows that even though only anonymous functions are used, it is possible to write recursive functions. Instead of naming the function directly (using define), the function is passed as argument to another function — and that function has names for its arguments.

Related

Creating a function which takes any number of functions as arguments

I'm having trouble figuring out how to go about creating a function that can take a series of the same function as arguments with the last argument as an operand. For example:
(func sqrt sqrt sqrt 390625)
The call above should return 5 as (sqrt 390625) > (sqrt 625) > (sqrt 25) > 5
I'm having trouble figuring out the exact way I should write this as any way I have tried has given me errors or achieved an infinite loop.
This the code is have so far:
(define func
(lambda L
(cond ( (equal? (length L) 2) ((car L) (cadr L)) ) ;; If the list consists of only 2 elements, carry out the function (element 1) onto the operand (element 2)
( #t (apply (car L) (func (cdr L))) ) ;; otherwise, apply the function (1st element) onto the rest of the list
)
)
)
The first condition works, for example returning 5 if i call (func sqrt 25), however the recursive call is throwing errors.
I would appreciate any help with this.
The OP doesn't provide a definition for chain, so that part is unclear, but I think that a fundamental problem here is that there is no recursive call to func; further, apply isn't used in the right position.
Instead of using (equal (length L) 2) as a base case, it might be nicer to make recursive calls as long as the first element in the input is a procedure, or otherwise just return the element:
#lang racket
(define multi-call
(lambda args
(let ((arg (car args)))
(if (procedure? arg)
(arg (apply multi-call (cdr args)))
arg))))
Here, when arg is a procedure, then it is applied to the result of calling multi-call recursively on the remaining arguments. Note that multi-call takes an arbitrary number of arguments, wrapping them in the list args. The reduction step provides (cdr args), which is a list of the remaining arguments. This means that apply should be used to call multi-call on those remaining arguments because multi-call expects an arbitrary number of arguments, not a list of arguments.
multi-call.rkt> (multi-call sqrt sqrt sqrt 390625)
5

I working through little lisper. The function lat? checks whether all elements of list are atoms or not

(defun lat
(lambda (l)
(cond ((null l) t)
((atom (car l))(lat (cdr l))
(t nil))))
The function takes a list as an argument. It is a recursive function that checks every element in the list. Whether it is atom or not. If every element is an atom, then it returns true else false.
Following is the error displayed
While compiling LAT :
Bad lambda list : (LAMBDA (L)
(COND ((NULL L) T) ((ATOM # #)) (T NIL)))
[Condition of type CCL::COMPILE-TIME-PROGRAM-ERROR]
Just like Hal Abelson called Scheme "lisp" in the SICP videos this book does the same, however the language in the book is a predecessor to Scheme and not Common Lisp. When you see:
(define name
(lambda (arg ...)
body ...)
This is the same as this in CL:
(defun name (arg ...)
body ...)
The reason is that in Scheme it's the same namespace for operator as well as operand bindings. A lisp-2 like Common Lisp can split it up like this:
(setf (fdefinition 'name)
(lambda (arg ...)
body ...))
This probably won't happen since you can always use defun, but in the event you return a function from a function you can do this or you must rely on funcall or apply to use the returned value:
;; This is a function that creates a function
(defun get-counter (from step)
(lambda ()
(let ((tmp from))
(incf from step)
tmp)))
When using this you might want to bind it globally:
(setf (fdefinition 'evens) (get-counter 0 2))
(evens) ; ==> 0
(evens) ; ==> 2
Or in functions you get it bound to normal variables and need to funcall or apply:
(defparameter *odds* (get-counter 1 2))
(funcall *odds*)
; ==> 1
Which one do you prefer?
(list (funcall *odds*) (evens))
; ==> (3 4)
The ? in lat? inidicated predicate and in CL a p in the end does the same. Your function latp is suppose to return nil or t so it should not return a function at all. Thus:
(defun latp (list)
(cond ((null list) t)
((atom (car list)) (latp (cdr list)))
(t nil)))
This of course is the same as:
(defun latp (list)
(or (null list)
(and (atom (car list))
(latp (cdr list)))))
Unlike Scheme using the name list as the argument does not affect the function call to list.

What is "named let" and how do I use it to implement a map function?

I'm totally new to Scheme and I am trying to implement my own map function. I've tried to find it online, however all the questions I encountered were about some complex versions of map function (such as mapping functions that take two lists as an input).
The best answer I've managed to find is here: (For-each and map in Scheme). Here is the code from this question:
(define (map func lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (func (car rest)) (recur (cdr rest))))))
It doesn't solve my problem though because of the usage of an obscure function recur. It doesn't make sense to me.
My code looks like this:
(define (mymap f L)
(cond ((null? L) '())
(f (car L))
(else (mymap (f (cdr L))))))
I do understand the logic behind the functional approach when programming in this language, however I've been having great difficulties with coding it.
The first code snippet you posted is indeed one way to implement the map function. It uses a named let. See my comment on an URL on how it works. It basically is an abstraction over a recursive function. If you were to write a function that prints all numbers from 10 to 0 you could write it liks this
(define (printer x)
(display x)
(if (> x 0)
(printer (- x 1))))
and then call it:
(printer 10)
But, since its just a loop you could write it using a named let:
(let loop ((x 10))
(display x)
(if (> x 0)
(loop (- x 1))))
This named let is, as Alexis King pointed out, syntactic sugar for a lambda that is immediately called. The above construct is equivalent to the snippet shown below.
(letrec ((loop (lambda (x)
(display x)
(if (> x 0)
(loop (- x 1))))))
(loop 10))
In spite of being a letrec it's not really special. It allows for the expression (the lambda, in this case) to call itself. This way you can do recursion. More on letrec and let here.
Now for the map function you wrote, you are almost there. There is an issue with your two last cases. If the list is not empty you want to take the first element, apply your function to it and then apply the function to the rest of the list. I think you misunderstand what you actually have written down. Ill elaborate.
Recall that a conditional clause is formed like this:
(cond (test1? consequence)
(test2? consequence2)
(else elsebody))
You have any number of tests with an obligatory consequence. Your evaluator will execute test1? and if that evaluated to #t it will execute the consequence as the result of the entire conditional. If test1? and test2? fail it will execute elsebody.
Sidenote
Everything in Scheme is truthy except for #f (false). For example:
(if (lambda (x) x)
1
2)
This if test will evaluate to 1 because the if test will check if (lambda (x) x) is truthy, which it is. It is a lambda. Truthy values are values that will evaluate to true in an expression where truth values are expected (e.g., if and cond).
Now for your cond. The first case of your cond will test if L is null. If that is evaluated to #t, you return the empty list. That is indeed correct. Mapping something over the empty list is just the empty list.
The second case ((f (car L))) literally states "if f is true, then return the car of L".
The else case states "otherwise, return the result mymap on the rest of my list L".
What I think you really want to do is use an if test. If the list is empty, return the empty list. If it is not empty, apply the function to the first element of the list. Map the function over the rest of the list, and then add the result of applying the function the first element of the list to that result.
(define (mymap f L)
(cond ((null? L) '())
(f (car L))
(else (mymap (f (cdr L))))))
So what you want might look look this:
(define (mymap f L)
(cond ((null? L) '())
(else
(cons (f (car L))
(mymap f (cdr L))))))
Using an if:
(define (mymap f L)
(if (null? L) '()
(cons (f (car L))
(mymap f (cdr L)))))
Since you are new to Scheme this function will do just fine. Try and understand it. However, there are better and faster ways to implement this kind of functions. Read this page to understand things like accumulator functions and tail recursion. I will not go in to detail about everything here since its 1) not the question and 2) might be information overload.
If you're taking on implementing your own list procedures, you should probably make sure they're using a proper tail call, when possible
(define (map f xs)
(define (loop xs ys)
(if (empty? xs)
ys
(loop (cdr xs) (cons (f (car xs)) ys))))
(loop (reverse xs) empty))
(map (λ (x) (* x 10)) '(1 2 3 4 5))
; => '(10 20 30 40 50)
Or you can make this a little sweeter with the named let expression, as seen in your original code. This one, however, uses a proper tail call
(define (map f xs)
(let loop ([xs (reverse xs)] [ys empty])
(if (empty? xs)
ys
(loop (cdr xs) (cons (f (car xs)) ys)))))
(map (λ (x) (* x 10)) '(1 2 3 4 5))
; => '(10 20 30 40 50)

Scheme Trying to check if a word in the list

I have a few functions.
(define adjs '(black brown fast hairy hot quick red slow))
(define adj?
(lambda (a) (if (member a adjs) #t #f)
)
(define OK
(lambda (x)
(cond
((equal? x()) #t)
((equal? adj? (car x)) OK(cdr x))
((else x #f))
)
)
)
The function adj? is checking to see if the input is part of the list of adjectives in adjs.
What I am trying to do with the OK function is the user will input a list and have that list run through adj? to see if it is part of the adjs list.
What happens when I run the function is I get an error return that says I entered in "X" amount of arguments when the function only expected two. Why?
There are problems with the parentheses. Some are unnecessary and others are missing, for example when you recursively call the OK procedure, or in the way you're calling adj? - remember, in Scheme we call a procedure like this: (f x), not like this: f(x). Also, the base case of the recursion seems off, and the else clause is used incorrectly. Try this:
(define adj?
(lambda (a)
(if (member a adjs) #t #f)))
(define OK
(lambda (x)
(cond
((null? x) #t)
((adj? (car x)) (OK (cdr x)))
(else #f))))

(compose) in Common Lisp

We find this function builder to realize composition in P.Graham's "ANSI Common Lisp" (page 110).
The arguments are n>0 quoted function names. I don't understand it completely, so I'll quote the code here and specify my questions underneath it:
(defun compose (&rest fns)
(destructuring-bind (fn1 . rest) (reverse fns)
#'(lambda (&rest args)
(reduce #'(lambda (v f) (funcall f v))
rest
:initial-value (apply fn1 args)))))
The argument list to compose is reversed and unpacked, its (now first) element bound to 'fn1' and the rest to 'rest'.
The body of the outermost lambda is a reduce: (funcall fi (funcall fi-1 ... ) ), with operands in inverted order to restore the initial one.
1) What is the role of the outermost lambda expression? Namely, where does it get its 'args' from? Is it the data structure specified as the first argument of destructuring-bind?
2) Where does the innermost lambda take its two arguments from?
I mean I can appreciate what the code does but still the lexical scope is a bit of a mystery to me.
Looking forward to any and all comments!
Thanks in advance,
//Marco
It's probably easier if you consider first a couple of practical examples:
(defun compose1 (a)
(lambda (&rest args)
(apply a args)))
(defun compose2 (a b)
(lambda (&rest args)
(funcall a (apply b args))))
(defun compose3 (a b c)
(lambda (&rest args)
(funcall a (funcall b (apply c args)))))
So the outermost lambda is the return value: a function that takes any arguments, what it does with it is applying the last function and chaining all the others in reverse order on the result got from last function.
Note: compose1 could be defined more simply as (defun compose1 (a) a).
A somewhat equivalent but less efficient version could be
(defun compose (&rest functions)
(if (= (length functions) 1)
(car functions)
(lambda (&rest args)
(funcall (first functions)
(apply (apply #'compose (rest functions))
args)))))
1) The outermost lambda creates a closure for you, because the result of (combine ...) is a function that calulates the composition of other functions.
2) The innermost lambda gets ists argument from the function reduce. Reduce takes a function (the innermost lambda) of two arguments and applies it stepwise to a list, e.g.
(reduce #'- '(1 2 3 4)) is (- (- (- 1 2) 3) 4)

Resources