First, untangle the two F
:
(defun foo (fun)
#'(lambda (n)
(if (zerop n)
(funcall fun n)
(1+ (funcall (foo fun) (1- n))))))
Now, you call:
(funcall (foo #'(lambda (x) (+ 2 x))) 2)
We can give the inner lambda a name, I'll call it add-2
.
(funcall (foo #'add-2) 2)
(Foo #'add-2)
then returns the function
(lambda (n)
(if (zerop n)
(funcall #'add-2 n) ; n is always 0 here
(1+ (funcall (foo #'add-2) (1- n)))))
This gets called with 2
, which is not zerop
, so it is:
(1+ (funcall (foo #'add-2) 1))
We already know what (foo #'add-2)
returns, and it gets called with 1
now, which still is not zerop
:
(1+ (1+ (funcall (foo #'add-2) 0)))
Now the argument is 0
, so we get to the base case:
(1+ (1+ (funcall #'add-2 0)))
We now can see that foo
creates a function that adds n
to the result of calling (fun 0)
.