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.
Related
Write a Racket function count-occurrences that consumes two lists of symbols and produces a list of
natural numbers measuring how many times items in the first list occur in the second list. For example:
(count-occurrences (list 'a 'b 'a 'q) (list 'r 'a 'b 'e 'b 'g))
=> (list 1 2 1 0)
I've been struggling with this question - how do I use map to do it, since for this question it's specified we can't use recursion.
My original idea was to do the following:
(define (count-occurrences los1 los2)
(map
(length (filter (lambda (x) (symbol=? x (first los1))) los2))
los1))
but using length here can only get us the number 'a occurred, instead of going into recursion. and for abstract functions there can only be one argument for the inside function, so I'm totally lost.
If ... x ... is an open formula, i.e. an expression which references an unbound variable x, wrapping it in a lambda form makes it a function in x, like so:
(lambda (x) ... x ... )
where x becomes bound by that lambda form; a parameter to this so called lambda function, which is to say, an anonymous function introduced by a lambda form.
So, the solution for your troubles is quite simple: recognize that
(length
(filter (lambda (x)
(symbol=? x (first los1)))
los2))
should actually be
(length
(filter (lambda (x)
(symbol=? x y))
los2))
where y refers to each of the elements of los1 in turn, not just the first one; and that it is then an open formula in y – that is to say, y is unbound, free, there. So we must capture it, and make it bound, by ... yes, enclosing this expression in a lambda form, thereby making it a function in y! Like so:
(lambda (y)
(length
(filter (lambda (x)
(symbol=? x y))
los2)))
And this is what gets mapped over los1.
With this simple tweak, your code becomes a correct, working function definition.
Does this fit your requirements and restrictions?
(define (count-occurrences lst1 lst2)
(map (lambda (e1)
(count (lambda (e2) (eq? e1 e2))
lst2))
lst1))
A good way to keep track of keys and values is with a hash-table. While it is possible to write count-occurrences using map and passing a lambda, being explicit may make it easier to see what is going on.
;;; list list -> list
;;;
(define (count-occurrences keys values)
;; Create data structure
(define ht (make-hash))
;; Initialize data structure with keys
;; Set the value of each key to zero
;; Since we have not started counting
(for ([k keys])
(hash-set! ht k 0))
;; Iterate over values and
;; Increment hash table if
;; When value is a key
(for ([v values])
(if (hash-has-key? ht v)
(hash-set! ht v (+ (hash-ref ht v) 1))
null))
;; Iterate over keys and
;; Create list of values
(for/list ([k keys])
(hash-ref ht k)))
Since recursion is prohibited, explicitly looping may make for more maintainable/readable code than an implicit loop. Besides, the variations of for are worth knowing. Hash tables have the advantage that duplicate keys read the same value and there is no need to track the same key twice.
One of the engineering advantages of using for rather than map is that it is easier to reason about the running time. The running time for this code is 2m + n where m is keys and n is values. Solutions using map will typically be m * n. There's nothing inherently wrong with that. But it is worth recognizing.
Does scheme have a function to call a function n times. I don't want map/for-each as the function doesn't have any arguments. Something along the lines of this :-
(define (call-n-times proc n)
(if (= 0 n)
'()
(cons (proc) (call-n-times proc (- n 1)))))
(call-n-times read 10)
SRFI 1 has a list-tabulate function that can build a list from calling a given function, with arguments 0 through (- n 1). However, it does not guarantee the order of execution (in fact, many implementations start from (- n 1) and go down), so it's not ideal for calling read with.
In Racket, you can do this:
(for/list ((i 10))
(read))
to call read 10 times and collect the result of each; and it would be done left-to-right. But since you tagged your question for Guile, we need to do something different.
Luckily, Guile has SRFI 42, which enables you to do:
(list-ec (: i 10)
(read))
Implementing tail-recursion modulo cons optimization by hand, to build the resulting list with O(1) extra space:
(define (iterate0-n proc n) ; iterate a 0-arguments procedure n times
(let ((res (list 1))) ; return a list of results in order
(let loop ((i n) (p res))
(if (< i 1)
(cdr res)
(begin
(set-cdr! p (list (proc)))
(loop (- i 1) (cdr p)))))))
This technique first (?) described in Friedman and Wise's TR19.
I have to define a variadic function in Scheme that takes the following form:
(define (n-loop procedure [a list of pairs (x,y)]) where the list of pairs can be any length.
Each pair specifies a lower and upper bound. That is, the following function call: (n-loop (lambda (x y) (inspect (list x y))) (0 2) (0 3)) produces:
(list x y) is (0 0)
(list x y) is (0 1)
(list x y) is (0 2)
(list x y) is (1 0)
(list x y) is (1 1)
(list x y) is (1 2)
Obviously, car and cdr are going to have to be involved in my solution. But the stipulation that makes this difficult is the following. There are to be no assignment statements or iterative loops (while and for) used at all.
I could handle it using while and for to index through the list of pairs, but it appears I have to use recursion. I don't want any code solutions, unless you feel it is necessary for explanation, but does anyone have a suggestion as to how this might be attacked?
The standard way to do looping in Scheme is to use tail recursion. In fact, let's say you have this loop:
(do ((a 0 b)
(b 1 (+ a b))
(i 0 (+ i 1)))
((>= i 10) a)
(eprintf "(fib ~a) = ~a~%" i a))
This actually get macro-expanded into something like the following:
(let loop ((a 0)
(b 1)
(i 0))
(cond ((>= i 10) a)
(else (eprintf "(fib ~a) = ~a~%" i a)
(loop b (+ a b) (+ i 1)))))
Which, further, gets macro-expanded into this (I won't macro-expand the cond, since that's irrelevant to my point):
(letrec ((loop (lambda (a b i)
(cond ((>= i 10) a)
(else (eprintf "(fib ~a) = ~a~%" i a)
(loop b (+ a b) (+ i 1)))))))
(loop 0 1 0))
You should be seeing the letrec here and thinking, "aha! I see recursion!". Indeed you do (specifically in this case, tail recursion, though letrec can be used for non-tail recursions too).
Any iterative loop in Scheme can be rewritten as that (the named let version is how loops are idiomatically written in Scheme, but if your assignment won't let you use named let, expand one step further and use the letrec). The macro-expansions I've described above are straightforward and mechanical, and you should be able to see how one gets translated to the other.
Since your question asked how about variadic functions, you can write a variadic function this way:
(define (sum x . xs)
(if (null? xs) x
(apply sum (+ x (car xs)) (cdr xs))))
(This is, BTW, a horribly inefficient way to write a sum function; I am just using it to demonstrate how you would send (using apply) and receive (using an improper lambda list) arbitrary numbers of arguments.)
Update
Okay, so here is some general advice: you will need two loops:
an outer loop, that goes through the range levels (that's your variadic stuff)
an inner loop, that loops through the numbers in each range level
In each of these loops, think carefully about:
what the starting condition is
what the ending condition is
what you want to do at each iteration
whether there is any state you need to keep between iterations
In particular, think carefully about the last point, as that is how you will nest your loops, given an arbitrary number of nesting levels. (In my sample solution below, that's what the cur variable is.)
After you have decided on all these things, you can then frame the general structure of your solution. I will post the basic structure of my solution below, but you should have a good think about how you want to go about solving the problem, before you look at my code, because it will give you a good grasp of what differences there are between your solution approach and mine, and it will help you understand my code better.
Also, don't be afraid to write it using an imperative-style loop first (like do), then transforming it to the equivalent named let when it's all working. Just reread the first section to see how to do that transformation.
All that said, here is my solution (with the specifics stripped out):
(define (n-loop proc . ranges)
(let outer ((cur ???)
(ranges ranges))
(cond ((null? ranges) ???)
(else (do ((i (caar ranges) (+ i 1)))
((>= i (cadar ranges)))
(outer ??? ???))))))
Remember, once you get this working, you will still need to transform the do loop into one based on named let. (Or, you may have to go even further and transform both the outer and inner loops into their letrec forms.)
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.).
The following example involves jumping into continuation and exiting out. Can somebody explain the flow of the function. I am moving in a circle around continuation, and do not know the entry and exit points of the function.
(define (prod-iterator lst)
(letrec ((return-result empty)
(resume-visit (lambda (dummy) (process-list lst 1)))
(process-list
(lambda (lst p)
(if (empty? lst)
(begin
(set! resume-visit (lambda (dummy) 0))
(return-result p))
(if (= 0 (first lst))
(begin
(call/cc ; Want to continue here after delivering result
(lambda (k)
(set! resume-visit k)
(return-result p)))
(process-list (rest lst) 1))
(process-list (rest lst) (* p (first lst))))))))
(lambda ()
(call/cc
(lambda (k)
(set! return-result k)
(resume-visit 'dummy))))))
(define iter (prod-iterator '(1 2 3 0 4 5 6 0 7 0 0 8 9)))
(iter) ; 6
(iter) ; 120
(iter) ; 7
(iter) ; 1
(iter) ; 72
(iter) ; 0
(iter) ; 0
Thanks.
The procedure iterates over a list, multiplying non-zero members and returning a result each time a zero is found. Resume-visit stores the continuation for processing the rest of the list, and return-result has the continuation of the call-site of the iterator. In the beginning, resume-visit is defined to process the entire list. Each time a zero is found, a continuation is captured, which when invoked executes (process-list (rest lst) 1) for whatever value lst had at the time. When the list is exhausted, resume-visit is set to a dummy procedure. Moreover, every time the program calls iter, it executes the following:
(call/cc
(lambda (k)
(set! return-result k)
(resume-visit 'dummy)))
That is, it captures the continuation of the caller, invoking it returns a value to the caller. The continuation is stored and the program jumps to process the rest of the list.
When the procedure calls resume-visit, the loop is entered, when return-result is called, the loop is exited.
If we want to examine process-list in more detail, let's assume the list is non-empty. Tho procedure employs basic recursion, accumulating a result until a zero is found. At that point, p is the accumulated value and lst is the list containing the zero. When we have a construction like (begin (call/cc (lambda (k) first)) rest), we first execute first expressions with k bound to a continuation. It is a procedure that when invoked, executes rest expressions. In this case, that continuation is stored and another continuation is invoked, which returns the accumulated result p to the caller of iter. That continuation will be invoked the next time iter is called, then the loop continues with the rest of the list. That is the point with the continuations, everything else is basic recursion.
What you need to keep in mind is that, a call to (call/cc f) will apply the function f passed as argument to call/cc to the current continuation. If that continuation is called with some argument a inside the function f, the execution will go to the corresponding call to call/cc, and the argument a will be returned as the return value of that call/cc.
Your program stores the continuation of "calling call/cc in iter" in the variable return-result, and begins processing the list. It multiplies the first 3 non-zero elements of the list before encountering the first 0. When it sees the 0, the continuation "processing the list element 0" is stored in resume-visit, and the value p is returned to the continuation return-result by calling (return-result p). This call will make the execution go back to the call/cc in iter, and that call/cc returns the passed value of p. So you see the first output 6.
The rest calls to iter are similar and will make the execution go back and forth between such two continuations. Manual analysis may be a little brain-twisting, you have to know what the execution context is when a continuation is restored.
You could achieve the same this way:
(define (prod-iter lst) (fold * 1 (remove zero? lst)))
... even though it could perform better by traversing only once.
For continuations, recall (pun intended) that all call/cc does is wait for "k" to be applied this way:
(call/cc (lambda (k) (k 'return-value)))
=> return-value
The trick here is that you can let call/cc return its own continuation so that it can be applied elsewhere after call/cc has returned like this:
;; returns twice; once to get bound to k, the other to return blah
(let ([k (call/cc (lambda (k) k))]) ;; k gets bound to a continuation
(k 'blah)) ;; k returns here
=> blah
This lets a continuation return more than once by saving it in a variable. Continuations simply return the value they are applied to.
Closures are functions that carry their environment variables along with them before arguments get bounded to them. They are ordinary lambdas.
Continuation-passing style is a way to pass closures as arguments to be applied later. We say that these closure arguments are continuations. Here's half of the current code from my sudoku generator/solver as an example demonstrating how continuation-passing style can simplify your algorithms:
#| the grid is internally represented as a vector of 81 numbers
example: (make-vector 81 0)
this builds a list of indexes |#
(define (cell n) (list (+ (* (car 9) (cadr n))))
(define (row n) (iota 9 (* n 9)))
(define (column n) (iota 9 n 9))
(define (region n)
(let* ([end (+ (* (floor-quotient n 3) 27)
(* (remainder n 3) 3))]
[i (+ end 21)])
(do ([i i
(- i (if (zero? (remainder i 3)) 7 1))]
[ls '() (cons (vector-ref *grid* i) ls)])
((= i end) ls))))
#| f is the continuation
usage examples:
(grid-ref *grid* row 0)
(grid-set! *grid* region 7) |#
(define (grid-ref g f n)
(map (lambda (i) (vector-ref g i)) (f n)))
(define (grid-set! g f n ls)
(for-each (lambda (i x) (vector-set! g i x))
(f n) ls))