trying to understand church encoding in Scheme - scheme

I'm trying to understand the whole principal of church encoding through Scheme. I think I understand the basics of it such as
Church numeral for 0
(define c-0
(lambda (f)
(lambda (x)
x)))
Church numeral for 1
(define c-1
(lambda (f)
(lambda (x)
(f x))))
... and continue applying the function to x N times.
Now my problem is just what does this all mean? If I take church-3 for example:
(define c-3
(lambda (x)
(lambda (f)
(f (f (f x))))))
What is this actually doing? I have only basic scheme knowledge as well but I don't even understand how to use the function? what is an example input using the c-3 function? is it just applying something 3 times like a loop?

You are right. c-3 in this case is a function, that takes 1 argument. And returns another function.
This other function takes a 1 argument function, and applies it to the first argument.
In this example, I'm calling c-3 with an argument of 3, this will return a function.
Then, I feed this function, another function, that add1 to x.
((c-3 3) (lambda (x) (add1 x)))
6
This will produce 6 as you see. It applies add1 to 3, 3 times. I know this is confusing. But you can
manually replace the arguments in the body of the function to understand it better. Wherever you see f, just replace that with (lambda (x) (add1 x)) And replace x with 3 (or any number).
This will work with any 1 argument function as long as the argument is of the correct type.

Related

Meaning of this Scheme interpreter output?

I'm working through Simply Scheme. I'm using DrRacket with this as my definitions file
https://gist.github.com/alexgian/5b351f367169b40a4ad809f0bb718e1f
I'm on exercise 17.3, which says
https://people.eecs.berkeley.edu/~bh/ssch17/lists.html
Describe the value returned by this invocation of map
> (map (lambda (x) (lambda (y) (+ x y))) '(1 2 3 4))
In DrRacket, I get the following output for that invocation of map:
(#<procedure> #<procedure> #<procedure> #<procedure>)
I know that lambda lets you return procedures. I'm having a hard time figuring out what procedure is being returned for some reason though, what exactly is happening here.
Simply substitute in turn every value of the list to the variable x in the inner function. In other words, the result is equal to:
(list (lambda (y) (+ 1 y))
(lambda (y) (+ 2 y))
(lambda (y) (+ 3 y))
(lambda (y) (+ 4 y)))
a list of four functions, each of them increasing its parameter by a different value.

Why does make-counter procedure contains two lambda definition?

I'm trying to understand the scheme code of make-counter procedure. It's a higher order procedure (a procedure outputs another procedure) and I'm stuck with it.
(define make-counter
(lambda (n)
(lambda ()
(set! n (+ n 1))
n)))
(define ca (make-counter 0))
(ca)
(ca)
This outputs 1 and 2 respectively as expected. Why do we need 2 nested procedures here? What are their functions individually?
I'd be appreciated if someone explains in details. Thanks from now on.
Indented properly, this is:
(define make-counter
(lambda (n)
(lambda ()
(set! n (+ n 1))
n)))
By the way, you can use a different syntax:
(define (make-counter n)
(lambda ()
(set! n (+ n 1))
n))
make-counter is a function that accepts a number n and returns an object called closure, which acts like a function but contains a state. Different invocations of make-counter will produce different closures, even when given the same n in argument. A closure can be called using the function-call syntax, as you experimented.
When you call the closure, the code that is contained within is executed. In your example, the closure accepts zero arguments, and mutates the variable named n. Again, the binding from n to a value is local to the closure and different for all instances of counters. But inside a particular counter, n always refer to the same memory location.
A call to the set! function changes what n evaluates to, and replaces the previous value with (+ n 1), incrementing the local counter variable.

Continuation Passing Style In Common Lisp?

In an effort to find a simple example of CPS which doesn't give me a headache , I came across this Scheme code (Hand typed, so parens may not match) :
(define fact-cps
(lambda(n k)
(cond
((zero? n) (k 1))
(else
(fact-cps (- n 1)
(lambda(v)
(k (* v n))))))))
(define fact
(lambda(n)
(fact-cps n (lambda(v)v)))) ;; (for giggles try (lambda(v)(* v 2)))
(fact 5) => 120
Great, but Scheme isn't Common Lisp, so I took a shot at it:
(defun not-factorial-cps(n k v)
(declare (notinline not-factorial-cps)) ;; needed in clisp to show the trace
(cond
((zerop n) (k v))
((not-factorial-cps (1- n) ((lambda()(setq v (k (* v n))))) v))))
;; so not that simple...
(defun factorial(n)
(not-factorial-cps n (lambda(v)v) 1))
(setf (symbol-function 'k) (lambda(v)v))
(factorial 5) => 120
As you can see, I'm having some problems, so although this works, this has to be wrong. I think all I've accomplished is a convoluted way to do accumulator passing style. So other than going back to the drawing board with this, I had some questions: Where exactly in the Scheme example is the initial value for v coming from? Is it required that lambda expressions only be used? Wouldn't a named function accomplish more since you could maintain the state of each continuation in a data structure which can be manipulated as needed? Is there in particular style/way of continuation passing style in Common Lisp with or without all the macros? Thanks.
The problem with your code is that you call the anonymous function when recurring instead of passing the continuation like in the Scheme example. The Scheme code can easily be made into Common Lisp:
(defun fact-cps (n &optional (k #'values))
(if (zerop n)
(funcall k 1)
(fact-cps (- n 1)
(lambda (v)
(funcall k (* v n))))))
(fact-cps 10) ; ==> 3628800
Since the code didn't use several terms or the implicit progn i switched to if since I think it's slightly more readable. Other than that and the use of funcall because of the LISP-2 nature of Common Lisp it's the identical code to your Scheme version.
Here's an example of something you cannot do tail recursively without either mutation or CPS:
(defun fmapcar (fun lst &optional (k #'values))
(if (not lst)
(funcall k lst)
(let ((r (funcall fun (car lst))))
(fmapcar fun
(cdr lst)
(lambda (x)
(funcall k (cons r x)))))))
(fmapcar #'fact-cps '(0 1 2 3 4 5)) ; ==> (1 1 2 6 24 120)
EDIT
Where exactly in the Scheme example is the initial value for v coming
from?
For every recursion the function makes a function that calls the previous continuation with the value from this iteration with the value from the next iteration, which comes as an argument v. In my fmapcar if you do (fmapcar #'list '(1 2 3)) it turns into
;; base case calls the stacked lambdas with NIL as argument
((lambda (x) ; third iteration
((lambda (x) ; second iteration
((lambda (x) ; first iteration
(values (cons (list 1) x)))
(cons (list 2) x)))
(cons (list 3) x))
NIL)
Now, in the first iteration the continuation is values and we wrap that in a lambda together with consing the first element with the tail that is not computed yet. The next iteration we make another lambda where we call the previous continuation with this iterations consing with the tail that is not computed yet.. At the end we call this function with the empty list and it calls all the nested functions from end to the beginning making the resulting list in the correct order even though the iterations were in oposite order from how you cons a list together.
Is it required that lambda expressions only be used? Wouldn't a named
function accomplish more since you could maintain the state of each
continuation in a data structure which can be manipulated as needed?
I use a named function (values) to start it off, however every iteration of fact-cps has it's own free variable n and k which is unique for that iteration. That is the data structure used and for it to be a named function you'd need to use flet or labels in the very same scope as the anonymous lambda functions are made. Since you are applying previous continuation in your new closure you need to build a new one every time.
Is there in particular style/way of continuation passing style in
Common Lisp with or without all the macros?
It's the same except for the dual namespace. You need to either funcall or apply. Other than that you do it as in any other language.

Using foldr with scheme

If I have a list of procedures. How can foldr be used to next the calls?
Like (new abs) => (new (abs x))
Note: foldr should return a procedure.
I have
(define next
(lambda (ls)
(foldr (lambda (x) x) (lambda (x) x) ls)))
But this is giving an error...
The first procedure passed to foldr must have two parameters, like this:
(define next
(lambda (ls)
(foldr (lambda (x a) <???>) ; It's not clear what do you want to do inside
(lambda (x) x) ; this is the identity function, what's it for?
ls)))
Just to be clear:
The first parameter to foldr is the procedure to be executed, and it receives two arguments: the first one is the current value in the list and the second the accumulated value so far
The second parameter to foldr is the initial value, it's suspicious that you're passing the identity function, I bet that's not right
The third parameter to foldr is the list to be processed
The second arg to foldr should be the initial value for the result, typically an empty list.

Which is the current continuation in the following expression?

In the expression (call/cc (lambda (k) (k 12))), there are three continuations: (k 12), (lambda (k) (k 12)), and (call/cc (lambda (k) (k 12))). Which one is the "current continuation"?
And continuations in some books are viewed as a procedure which is waiting for a value and it will return immediately when it's applied to a value. Is that right?
Can anyone explain what current continuations are in detail?
Things like (k 12) are not continuations. There is a continuation associated with each subexpression in some larger program. So for example, the continuation of x in (* 3 (+ x 42)) is (lambda (_) (* 3 (+ _ 42))).
In your example, the "current continuation" of (call/cc (lambda (k) (k 12))) would be whatever is surrounding that expression. If you just typed it into a scheme prompt, there is nothing surrounding it, so the "current continuation" is simply (lambda (_) _). If you typed something like (* 3 (+ (call/cc (lambda (k) (k 12))) 42)), then the continuation is (lambda (_) (* 3 (+ _ 42))).
Note that the lambdas I used to represent the "current continuation" are not the same as what call/cc passes in (named k in your example). k has a special control effect of aborting the rest of the computation after evaluating the current continuation.
The continuation in this case is the "thing" that receives the return value of the call/cc invocation. Thus:
(display (call/cc (lambda (k) (k 12)))
has the same result as
(display 12)
Continuations in Scheme "look and feel" like procedures, but they do not actually behave like procedures. One thing that can help you understand continuations better is CPS transformations.
In CPS transformation, instead of a function returning a value, instead it takes a continuation parameter, and invokes the continuation with the result. So, a CPS-transformed sqrt function would be invoked with (sqrt 64 k) and rather than returning 8, it just invokes (k 8) in tail position.
Because continuations (in a CPS-transformed function) are tail-called, the function doesn't have to worry about the continuation returning, and in fact, in most cases, they are not expected to return.
With this in mind, here's a simple example of a function:
(define (hypot x y)
(sqrt (+ (* x x) (* y y))))
and its CPS-transformed version:
(define (hypot x y k)
(* x x (lambda (x2)
(* y y (lambda (y2)
(+ x2 y2 (lambda (sum)
(sqrt sum k))))))))
(assuming that *, +, and sqrt have all been CPS-transformed also, to accept a continuation argument).
So now, the interesting part: a CPS-transformed call/cc has the following definition:
(define (call/cc fn k)
(fn k k))
With CPS transformation, call/cc is easy to understand and easy to implement. Without CPS transformation, call/cc is likely to require a highly magical implementation (e.g., via stack copying, etc.).

Resources