I am learning continuations but I can't wrap my head around this code. Why does it go into infinite loop?
(let ((cont #f))
(call/cc (lambda (k)
(set! cont k)))
(cont #f))
Line by line:
we define local variable cont
we call with current continuation some lambda function, that is, we are passing the current continuation to the lambda function as an argument. Current continuation is a function of 1 argument, this argument is then used as a "return value" of call/cc (and here is eventually ignored).
So k here signifies everything, that will happen after, in our case something close in sense to (lambda (call/cc-retval) (let () call/cc-retval (cont #f))). We set cont value to this continuation. call/cc returns.
Since cont is now a function which represented the continuation, and it's argument is the "return value of call/cc", we just call that function, the argument gets ignored, and we need to call the (cont #f) again.
Thus, what we get eventually is infinite loop.
Related
I’m trying to learn to program with the book Clojure for the Brave and True (CFTBAT). At the end of the crash course, the author makes us write a small programm to illustrate looping in Clojure. To explain the looping and recursing part of the program, here, the author writes a smaller example using loop and then shows it’s possible to replace loop with a normal function definition.
It’s this normal function definition example I can’t understand. Here is the code:
(defn recursive-printer
([]
(recursive-printer 0))
([iteration]
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recursive-printer (inc iteration)))))
(recursive-printer)
I don’t understand the code because I can’t see where are the arguments of the function recursive-printer. In Clojure, the arguments of a function are supposed to be in brackets and the body in parenthesis. So, in this example, the arguments would be an empty argument [] and iteration. But then why are they put between parenthesis too?
And what is (recursive-printer 0) Is it a function call, where the function calls itself?
If someone could explain me how this piece of code works, that would be much appreciated.
In clojure you can define a function such that it can take different numbers of
arguments e.g.
(defn foo []
....)
is a function which takes no arguments. It is called like this ..
(foo)
(defn foo [x]
...)
is a function which takes 1 argument. It can be called like
(foo :a)
but sometimes, you may want to define a function which takes zero or 1
argument. To do this, you use a slightly different format
(defn foo
([] ;no argument form
...)
([x] ;single argument form
...))
A common idiom is to use a zero argument form in a recursive function definition
and include a single 'accumulator' argument form as the main part of the
function. So, looking at your example, you have
(defn recursive-printer
([] ; zero argument form
(recursive-printer 0))
([iteration] ; 1 argument form
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recursive-printer (inc iteration)))))
(recursive-printer)
When you call (recursive-printer) it calls the first form (zero argument
form). That form in turn calls the function with a single argument of 0. This
calls the second form.
The second form first prints out the argument, then tests to see if it is
greater than 3, which in the first call it is not as it is 0, so it executes the
'else' statement, which does a recursive call with a new argument which is the
current argument increased by 1. Now your argument is 1 and it is printed
out. the test is still false as 1 is not > 3, so the function is called again
with the argument increased by 1 i.e. 2. In this call, 2 is printed, the test is
still not grater than three, so the function is called again with the argument
increased to 3. In this call, 3 is printed and the test is still not > 3, so the
argument is incremented to 4 and the function called again with 4 as the
argument. The value 4 is printed, but this time 4 is > 3, so the string "Bye" is
printed and as this is the terminating condition, no further recursive call is
made and the stack unwinds and the function terminates.
We can drop the zero arity:
(defn recursive-printer [iteration]
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recursive-printer (inc iteration))))
... and call the function with an explicit 0 argument:
(recursive-printer 0)
0
1
2
3
4
Bye!
=> nil
This lets us concentrate on the recursion. Since the recursive call is the last thing done (in tail position), we can use recur instead:
(defn recursive-printer [iteration]
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recur (inc iteration))))
... with exactly the same effect.
The extra arity just confuses things, I think.
I am attempting to write a loop in Scheme using named let. I would like to be able to break out of the iteration early based on various criteria, rather than always looping right at the end. Effectively, I would like to have while, break and continue. I am constrained to use guile 1.8 for strong reasons, and guile 1.8 does not implement the R6RS while construct. My question is, does recursing using named let have to be tail recursive, and why can't you restart the loop before the end? [Does this need a code example?] When I do attempt to recurse using an early exit at several point with IO operations I invariably read past EOF and get unpredictable corruption of data.
(let name ((iter iter-expr) (arg1 expr1) (arg2 expr2))
(cond
(continue-predicate (name (next iter) arg1 arg2)))
(break-predicate break-expression-value)
(else (name (next iter) next-arg1-expression next-ar2-expression))))
A continue is just calling again using most of the same arguments unchanged except the iterated parts which will change to the next thing.
A break is a base case.
So what is a while? It is a named let with a break predicate and a default case.
Scheme doesn't really have a while construct. If you read the report you'll see that it is just a syntax sugar (macro) that turns into something like a named let.
You need it to be tail recursive if you want to be able to exit it without all the previous calculations to be done. You can also use call/cc to supply an exit continuation which is basically having Scheme doing it for you under the hood. Usually call/cc is quite far out for beginners and it takes some time to master so making your procedures tail recursive is easier to understand than doing something like this:
(define (cars lists-of-pair)
(call/cc (lambda (exit)
(fold (lambda (e a)
(if (pair? e)
(cons (car e) a)
(exit '()))) ; throw away continuations to make current result make it ()
'()
lists-of-pair)))
(cars '((1 2) (a b))) ; ==> (1 a)
(cars '((1 2) ())) ; ==> ()
I am able to set a default argument and do a regular recursion with it, but for some reason I cannot do with recur for tail optimization... I keep getting an java.lang.UnsupportedOperationException: nth not supported on this type: Long error.
For example, for a Tail Call Factorial, here is what works, but isn't optimized for tail call recursion and will fail for large recursion stacks.
(defn foo [n & [optional]]
(if (= n 0) (or optional 1)
(foo (dec n) (*' (or optional 1) n))))
And I call this by (foo 3)
And when I try this to get TCO, I get the unsupported operation error...
(defn foo [n & [optional]]
(if (= n 0) (or optional 1)
(recur (dec n) (*' (or optional 1) n))))
And I call this one the same way (foo 3)
Why is this difference causing an error? How exactly would I be able to do TCO with optional default arguments?
Thank you!
EDIT:
and when I try to take out the (or optional 1) in the recursion call and make it just optional , i get a null exception error... Which makes sense.
This also does not get fixed when I try to remove the ' from *' in the recursion call
EDIT: I would also prefer to do this without loop as well
It is a known issue:
Recur doesn't re-enter the function, it just goes back to the top (the vararging doesn't happen again) ... recur with a collection and you will be fine.
I personally feel it should either be mentioned in the recur docstring, or at least appear in the doc. Takes a bit of digging to understand what's happening (I had to check Clojure compiler source along with the compiled classes.)
Why is this difference causing an error?
In short, it's trying to destructure a Long, which it can't
Straight foo call
Takes n arguments
Automatically puts everything after the first argument (n) into a seq behind the scenes, which can be destructured
recur call to foo
Takes exactly 2 arguments
First argument: n
Second argument: Something seqable with the rest of the arguments
How exactly would I be able to do TCO with optional default arguments?
Simply wrap the second argument to recur like so:
(defn foo [n & [optional]]
(if (= n 0) (or optional 1)
(recur (dec n) [(*' (or optional 1) n)])))
(foo 3)
;;=> 6
Recommendations
Although he didn't answer your questions, #DanielCompton's recommendation is the way to go to completely avoid the problem in the first place in a clearer and more efficient way
You can give a function multiple different arities. This might be what you're after?
(defn foo
([n]
(foo n 1))
([n optional]
(if (= n 0)
(or optional 1)
(recur (dec n) (*' (or optional 1) n)))))
I don't quite understand why there is an error, but recur wouldn't normally be used in a function with optional arguments.
Edit: after reading the other answer links, I understand the problem now. recur doesn't destructure the rest args like it does when you call the function. If you recur with a collection as the second arg, it will work, but it is probably still better to be explicit with two different arities:
(defn foo [n & [optional]]
(if (= n 0)
(or optional 1)
(recur (dec n) [(*' (or optional 1) n)])))
Here are some sample codes from text of OnLisp.
My question is that why it bothers to use a lambda function,
`(funcall (alrec ,rec #'(lambda () ,base)) ,#lsts))
as second argument to alrec in the definition of on-cdrs?
What is the difference if I just define it without using lambda?
`(funcall (alrec ,rec ,base) ,#lsts))
(defun lrec (rec &optional base)
(labels ((self (lst)
(if (null lst)
(if (functionp base)
(funcall base)
base)
(funcall rec (car lst)
#'(lambda ()
(self (cdr lst)))))))
#'self))
(defmacro alrec (rec &optional base)
"cltl2 version"
(let ((gfn (gensym)))
`(lrec #'(lambda (it ,gfn)
(symbol-macrolet ((rec (funcall ,gfn)))
,rec))
,base)))
(defmacro on-cdrs (rec base &rest lsts)
`(funcall (alrec ,rec #'(lambda () ,base)) ,#lsts))
You don't say how this is intended to be called and this code is a bit of a tangle so at a quick glance I couldn't say how it's supposed to work. However, I can answer your question.
First, let me say that
(if (functionp base) (funcall base) base)
is terrible programming style. This effectively puts a whole in your semantic space, creating a completely different handling of functions as objects than other things as objects. In Common Lisp, a function is supposed to be an object you can choose to pass around. If you want to call it, you should do so, but you shouldn't just say to someone "if I give you a function you should call it and otherwise you should not." (Why this matters will be seen as you read on.)
Second, as Barmar notes, if you write ,base you are basically saying "take the code and insert it for evaluation here". If you write
#'(lambda () ,base)
you are saying put the code inside a function so that its execution is delayed. Now, you're passing it to a function that when it receives the function is going to call it. And, moreover, calling it will evaluate it in the lexical environment of the caller, and there is no intervening change in dynamic state. So you'd think this would be the same thing as just evaluating it at the call site (other than just a little more overhead). However, there is a case where it's different.
If the thing you put in the base argument position is a variable (let's say X) or a number (let's say 3), then you'll either be doing (lrec ... X) or (lrec 3) or else you'll be doing
(lrec ... #'(lambda () X))
or
(lref ... #'(lambda () 3))
So far so good. If it gets to the caller, it's going to say "Oh, you just meant the value of X (or of 3)." But there's more...
If you say instead an expression that yields a function in the base argument position of your call to on-cdrs or your call to alrec, you're going to get different results depending on whether you wrote ,base or #'(lambda () ,base). For example, you might have put
#'f
or
#'(lambda () x)
or, even worse,
#'(lambda (x) x)
in the base argument position. In that case, if you had used ,base, then that expression would be immediately evaluated before passing the argument to lrec, and then lrec would receive a function. And then it would be called a second time (which is probably not what the macro user expects unless the documentation is very clear about this inelegance and the user of the macro has cared enough to read the documentation in detail). In the first case, it will return 3, in the second case, the value of x, and in the third case an error situation will occur because it will be called with the wrong number of arguments.
If instead you implemented it with
#'(lambda () ,base)
then lrec will receive as an argument the result of evaluating one of
#'(lambda () #'f)
or
#'(lambda () #'(lambda () 3))
or
#'(lambda () #'(lambda (x) x))
depending on what you gave it as an argument from our examples above. But in any case what lrec gets is a function of one argument that, when evaluated, will return the result of evaluating its body, that is, will return a function.
The important takeaways are these:
The comma is dropping in a piece of evaluable code, and wrapping the comma'd experession with a lambda (or wrapping any expression with a lambda) delays evaluation.
The conditional in the lrec definition should either expect that the value is already evaluated or not, and should not take a conditional effect because it can't know whether you already evaluated something based purely on type unless it basically makes a mess of functions as first-class data.
I hope that helps you see the difference. It's subtle, but it's real.
So using
#'(lambda () ,base)
protects the macro from double-evaluation of a base that might yield a function, but on the other hand the bad style is something that shouldn't (in my view) happen. My recommendation is to remove the conditional function call to base and make it either always or never call the base as a function. If you make it never call the function, the caller should definitely use ,base. If you make it always call the function, the caller should definitely include the lambda wrapper. That would make the number of evaluations deterministic.
Also, as a purely practical matter, I think it's more in the style of Common Lisp just to use ,base and not bother with the closure unless the expression is going to do something more than travel across a function call boundary to be immediately called. It's a waste of time and effort and perhaps extra consing to have the function where it's really not serving any interesting purpose. This is especially true if the only purpose of the lrec function is to support this facility. If lrec has an independent reason to have the contract that it does, that's another matter and maybe you'd write your macro to accommodate.
It's more common in a functional language like Scheme, which has a different aesthetic, to have a regular function as an alternative to any macro, and to have that function take such a zero-argument function as an argument just in case some user doesn't like working with macros. But mostly Common Lisp programmers don't bother, and your question was about Common Lisp, so I've biased the majority of my writing here to that dialect.
I'm writing a recursive Lisp macro taking a number n and evaluating the body n times (an exercise from ANSI Lisp). I've tried two ways of doing this -- having the macro call itself in its expansion, and having the macro expand into a local recursive function. Neither works as I want it to.
Here's the first one -- it has a stack overflow, but when I look at its expansion using macroexpand-1 it seems fine to me.
(defmacro n-times (n &rest body)
(let ((i (gensym)))
`(let ((,i ,n))
(if (zerop ,i) nil
(progn
,#body
(n-times (- ,i 1) ,#body))))))
Here's the second one -- it makes an error, "undefined function #xxxx called with arguments (z)" where #xxxx is the name of the gensym and z is 1 less than the number I call it with. I think there's a problem with the way I use gensyms and flet together, but I'm not sure how to do this correctly.
(defmacro n-times (n &rest body)
(let ((g (gensym)))
`(flet ((,g (x)
(if (zerop x) nil
(progn
,#body
(,g (- x 1))))))
(,g ,n))))
To answer your first question, you have a recursive macro expansion that never stops recursing. The presence of the if doesn't stop the recursive macro expansion, since macro expansion happens at compile-time and your if happens at run-time.
To answer your second question, you can't use flet to specify recursive functions, you have to use labels instead.
Since macro expansion in Common Lisp happens kind of before runtime, this is slightly tricky.
Remember, the macro sees source code. This means:
the number n must be passed as a number, not a variable, when you use the macro. Thus at macro expansion time the number is known. For such a macro, I would check that in the macro - otherwise you always be tempted to write something like (let ((n 10)) (n-times n ...)) - which won't work.
the macro needs to compute the recursive iteration. Thus the logic is in the macro, and not in the generated code. Each macro needs to generate code, which is one step simpler at macro expansion time - until the basic case is reached.