Scheme continuation unexpeded behavior - functional-programming

Here is my code. As I call continuation twice, I expect "world" be displayed twice.
But it output only once. What am I missing?
(define call-with-current-continuation call/cc)
(define (repeat arg)
(lambda (cc)
(cc arg)
(cc arg)))
(display (call/cc (repeat "world")))

The short version: the continuation you're capturing is bigger than you think it is. When scheme is evaluating the "call/cc", the continuation is "display this result and then exit the program". So, the first call to the continuation inside the body of the (lambda (cc) (cc arg) (cc arg)) will print the value ... and then exit the program.
To get the behavior you want, you probably want a delimited continuation, that captures only the portion of the continuation out to the top level. Different Scheme implementations differ in the availability of delimited continuations (though you can implement delimited continuations in terms of full continuations, at the expense of efficiency).
Racket, for instance, has a "call with composable continuation" that slices off only the portion of the continuation that reaches out to the nearest prompt... and there's an implicit prompt around each top-level expression. So this program:
#lang racket
(define (repeat arg)
(lambda (cc)
(cc arg)
(cc arg)))
(display (call-with-composable-continuation (repeat "world")))
prints "world" twice, as you'd hoped.

Related

Reversing list vs non tail recursion when traversing lists

I wonder how do you, experienced lispers / functional programmers usually make decision what to use. Compare:
(define (my-map1 f lst)
(reverse
(let loop ([lst lst] [acc '()])
(if (empty? lst)
acc
(loop (cdr lst) (cons (f (car lst)) acc))))))
and
(define (my-map2 f lst)
(if (empty? lst)
'()
(cons (f (car lst)) (my-map2 f (cdr lst)))))
The problem can be described in the following way: whenever we have to traverse a list, should we collect results in accumulator, which preserves tail recursion, but requires list reversion in the end? Or should we use unoptimized recursion, but then we don't have to reverse anything?
It seems to me the first solution is always better. Indeed, there's additional complexity (O(n)) there. However, it uses much less memory, let alone calling a function isn't done instantly.
Yet I've seen different examples where the second approach was used. Either I'm missing something or these examples were only educational. Are there situations where unoptimized recursion is better?
When possible, I use higher-order functions like map which build a list under the hood. In Common Lisp I also tend to use loop a lot, which has a collect keyword for building list in a forward way (I also use the series library which also implements it transparently).
I sometimes use recursive functions that are not tail-recursive because they better express what I want and because the size of the list is going to be relatively small; in particular, when writing a macro, the code being manipulated is not usually very large.
For more complex problems I don't collect into lists, I generally accept a callback function that is being called for each solution. This ensures that the work is more clearly separated between how the data is produced and how it is used.
This approach is to me the most flexible of all, because no assumption is made about how the data should be processed or collected. But it also means that the callback function is likely to perform side-effects or non-local returns (see example below). I don't think it is particularly a problem as long the the scope of the side-effects is small (local to a function).
For example, if I want to have a function that generates all natural numbers between 0 and N-1, I write:
(defun range (n f)
(dotimes (i n)
(funcall f i)))
The implementation here iterates over all values from 0 below N and calls F with the value I.
If I wanted to collect them in a list, I'd write:
(defun range-list (N)
(let ((list nil))
(range N (lambda (v) (push v list)))
(nreverse list)))
But, I can also avoid the whole push/nreverse idiom by using a queue. A queue in Lisp can be implemented as a pair (first . last) that keeps track of the first and last cons cells of the underlying linked-list collection. This allows to append elements in constant time to the end, because there is no need to iterate over the list (see Implementing queues in Lisp by P. Norvig, 1991).
(defun queue ()
(let ((list (list nil)))
(cons list list)))
(defun qpush (queue element)
(setf (cdr queue)
(setf (cddr queue)
(list element))))
(defun qlist (queue)
(cdar queue))
And so, the alternative version of the function would be:
(defun range-list (n)
(let ((q (queue)))
(range N (lambda (v) (qpush q v)))
(qlist q)))
The generator/callback approach is also useful when you don't want to build all the elements; it is a bit like the lazy model of evaluation (e.g. Haskell) where you only use the items you need.
Imagine you want to use range to find the first empty slot in a vector, you could do this:
(defun empty-index (vector)
(block nil
(range (length vector)
(lambda (d)
(when (null (aref vector d))
(return d))))))
Here, the block of lexical name nil allows the anonymous function to call return to exit the block with a return value.
In other languages, the same behaviour is often reversed inside-out: we use iterator objects with a cursor and next operations. I tend to think it is simpler to write the iteration plainly and call a callback function, but this would be another interesting approach too.
Tail recursion with accumulator
Traverses the list twice
Constructs two lists
Constant stack space
Can crash with malloc errors
Naive recursion
Traverses list twice (once building up the stack, once tearing down the stack).
Constructs one list
Linear stack space
Can crash with stack overflow (unlikely in racket), or malloc errors
It seems to me the first solution is always better
Allocations are generally more time-expensive than extra stack frames, so I think the latter one will be faster (you'll have to benchmark it to know for sure though).
Are there situations where unoptimized recursion is better?
Yes, if you are creating a lazily evaluated structure, in haskell, you need the cons-cell as the evaluation boundary, and you can't lazily evaluate a tail recursive call.
Benchmarking is the only way to know for sure, racket has deep stack frames, so you should be able to get away with both versions.
The stdlib version is quite horrific, which shows that you can usually squeeze out some performance if you're willing to sacrifice readability.
Given two implementations of the same function, with the same O notation, I will choose the simpler version 95% of the time.
There are many ways to make recursion preserving iterative process.
I usually do continuation passing style directly. This is my "natural" way to do it.
One takes into account the type of the function. Sometimes you need to connect your function with the functions around it and depending on their type you can choose another way to do recursion.
You should start by solving "the little schemer" to gain a strong foundation about it. In the "little typer" you can discover another type of doing recursion, founded on other computational philosophy, used in languages like agda, coq.
In scheme you can write code that is actually haskell sometimes (you can write monadic code that would be generated by a haskell compiler as intermediate language). In that case the way to do recursion is also different that "usual" way, etc.
false dichotomy
You have other options available to you. Here we can preserve tail-recursion and map over the list with a single traversal. The technique used here is called continuation-passing style -
(define (map f lst (return identity))
(if (null? lst)
(return null)
(map f
(cdr lst)
(lambda (r) (return (cons (f (car lst)) r))))))
(define (square x)
(* x x))
(map square '(1 2 3 4))
'(1 4 9 16)
This question is tagged with racket, which has built-in support for delimited continuations. We can accomplish map using a single traversal, but this time without using recursion. Enjoy -
(require racket/control)
(define (yield x)
(shift return (cons x (return (void)))))
(define (map f lst)
(reset (begin
(for ((x lst))
(yield (f x)))
null)))
(define (square x)
(* x x))
(map square '(1 2 3 4))
'(1 4 9 16)
It's my intention that this post will show you the detriment of pigeonholing your mind into a particular construct. The beauty of Scheme/Racket, I have come to learn, is that any implementation you can dream of is available to you.
I would highly recommend Beautiful Racket by Matthew Butterick. This easy-to-approach and freely-available ebook shatters the glass ceiling in your mind and shows you how to think about your solutions in a language-oriented way.

Is it possible to check if the current continuation is terminating?

Is it possible to define a procedure f such that it prints Exiting... if it is the last thing to do before exiting, and prints Not done yet... otherwise?
For examples,
(display "hello, world\n")
(f)
should give
hello, world
Exiting...
While
(f)
(display "bye, world\n")
should give
Not done yet...
bye, world
I have thought about using control operators such as shift / reset, but with no success. The key difficulty seems to be that there is no way to tell if the current continuation is terminating. Any idea?
A continuation is never empty. What happens after the end is implementation specific but there is always some sort of resource deallocation and shutdown.
So imagine you have the following code which I had high hopes for:
(call/cc (lambda (end)
(define (f)
(call/cc (lambda (c)
(if (eq? c end)
(display "bye, world\n")
(display "Not done yet...")))))
(f)
(display "hello, world\n")
(f)))
Now you are not guaranteed that the continuation c and end can be compared even if they ae the same continuation. This has to do with the language details that upto R6RS there were no way to compare two procedures and that we aren't really comparing procedures so the implementation might have open coded their halt continuation such that it gets wrapped in a lambda and thus you are really comparing (eq? (lambda (v) (halt)) (lambda (v) (halt))) and it is not guaranteed to be #t or #f.

Return to top-level call of a recursive function in Lisp

I have a recursive function which needs to recurse until it finds a certain result. However in the body of my function after my first recursive call I might do some other calculations or possibly recurse again. But, if I recurse and find the result I'm looking for, then I'd like to just stop out of any recursive I've been doing and return that result to avoid doing unnecessary computations.
In a normal recursive call once you get to the "base case" that gets returned to the function that called, then that gets returned to the one that called it, and so on. I'd like to know how to just return to the very first time the function was called, and not have to return something for all those intermediate steps.
For my basic recursion I could write a function like this:
(defun recurse (x)
(if (= x 10)
(return-from recurse x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse 1)
It has been written to illustrate what I mean about the function running more computations after a recursive call. And, as written this doesn't even return the value I'm interested in since I do some printings after I've returned the value I care about. (Note: The return-from command is extraneous here as I could just write "x" in its place. It's just there to draw parallels for when I try to return to the top level recursion in my second example below.)
Now, if I want to ditch all those extra "Recursed!" printings I could encase everything in a block and then just return to that block instead:
EDIT: Here is a function wrapper for my original example. This example should be clearer now.
(defun recurse-to-top (start)
(block top-level
(labels ((recurse (x)
(if (= x 10)
(return-from top-level x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse start))))
And running this block keeps going until 10 "is found" and then returns to from the top-level block with no extraneous printing, just like I wanted. But, this seems like a really clunky way to get this feature. I'd like to know if there's a standard or "best" way for getting this type of behavior.
DEFUN already sets up a lexical block:
(defun recurse (start)
(labels ((recurse-aux (x)
(case x
(10 (return-from recurse x))
(15 x)
(otherwise
(recurse-aux (+ x 1))
(print "Recursed!")))))
(recurse-aux start)))
Older is the use of CATCH and THROW, which is a more dynamic construct and thus allows an exit across functions:
(defun recurse (start)
(catch 'recurse-exit
(recurse-aux start)))
(defun recurse-aux (x)
(case x
(10 (throw 'recurse-exit x))
(15 x)
(otherwise
(recurse-aux (+ x 1))
(print "Recursed!")))))
(recurse-aux start))))
As mentioned by Lars, there are even more way to program control flow like this.
You want some kind of non-local exit. There are a few choices: return-from, go, throw, signal.
Maybe some variation on this?
(defun recurse (x &optional (tag 'done))
(catch tag
(when (= x 10)
(throw 'done x))
(recurse (1+ x) nil)
(print "Cursed!")))
I believe it does what you want, although there may be a lot of needless catching going on.
As always with Lisp, you can imagine there is a perfect language for your problem, and write your program in that language. E.g. something like
(defun recurse (x)
(top-level-block recurse
(when (= x 10)
(return-from-top-level recurse x))
(recurse (1+ x))
(print "Cursed!")))
Then there is just a simple matter of programming to implement the new macros top-level-block and return-from-top-level.
Imperfect sample code follows:
(defmacro top-level-block (name &body body)
`(if (boundp ',name)
(progn ,#body)
(catch ',name
(let ((,name t))
(declare (special ,name))
,#body))))
(defmacro return-from-top-level (name value)
`(throw ',name ,value))

Racket: Identifying tail recursion?

I wrote two different functions in racket to determine whether a list of numbers is ascending:
(define (ascending list)
(if (<= (length list) 1)
#t
(and (< (car list) (car (cdr list))) (ascending (cdr list)))))
(define (ascending-tail list)
(ascending-tail-helper #t list))
(define (ascending-tail-helper prevBool rest)
(if (<= (length rest) 1)
prevBool
(ascending-tail-helper (and prevBool (< (car rest) (car (cdr rest)))) (cdr rest))))
I had the hardest time determining whether or not the first ascending was tail recursive, so I rewrote it using what I believe to be tail recursion.
The reason why I retrospectively believe the first one to not be tail recursive is that I believe at each level of recursion, the function will be waiting for the second argument in the "and" statement to return before it can evaluate the boolean expression. Conversely, for ascending-tail-helper, I am able to evaluate the lesser than expression before I do my recursive call.
Is this correct, or did I make myself even more confused than before?
DrRacket can help you determine whether a call is in tail position or not. Click the "Syntax Check" button. Then move the mouse pointer to the left parenthesis of the expression in question. In your example I get this:
The purple arrow shows that the expression is in tail-position.
From the manual:
Tail Calls: Any sub-expression that is (syntactically) in
tail-position with respect to its enclosing context is annotated by
drawing a light purple arrow from the tail expression to its
surrounding expression.
You are correct, in the first version the recursive call returns to and, whereas in the second version the recursive call is a tail call.
However, and is a macro, and is generally expanded using if
(define (ascending list)
(if (<= (length list) 1)
#t
(if (< (car list) (car (cdr list)))
(ascending (cdr list))
#f)))
which is tail recursive.
One of the requirements for a function to be in tail position is that it's return value be usable as the return value of the parent function without modification or inspection. That is, the parent function should be able to return immediately, having evaluated the tail position statement.
On first appearance, your first function,inspects the return value of ascending. It seems that doesn't return ascending's value but, instead, a value derived from it. However, according to the relevant section of the R5RS spec, the final expression in an and statement is in tail position. (When I'm properly awake, I know this)
So you are wrong.
http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-6.html#%_sec_3.5
(Note: edited to correct my initial hasty answer).
Racket's documentation on tail positions says that the place to check what's in tail position and what's not is the documentation for the particular form:
Tail-position specifications provide a guarantee about the asymptotic space consumption of a computation. In general, the specification of tail positions goes with each syntactic form, like if.
Racket's docs on and say (emphasis added):
(and expr ...)
If no exprs are provided, then result is #t.
If a single expr is provided, then it is in tail position, so the
results of the and expression are the results of the expr.
Otherwise, the first expr is evaluated. If it produces #f, the result
of the and expression is #f. Otherwise, the result is the same as an
and expression with the remaining exprs in tail position with respect
to the original and form.

Why is it legal in a function definition to make self-call but illegal for a value?

Structure and Interpretation of Computer Programs (SICP) 3.5.2 introduces infinite streams:
(define ones
(cons-stream 1 ones))
This code doesn't work in DrRacket, with the error:
ones: undefined; cannot reference an identifier before its definition
Other code like this:
(define (integers-starting-from n)
(cons-stream n
(integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
produce error:
Interactions disabled
(fall in infinite loop?)
So far as I read(SICP), the key point of implementing an infinite stream is delayed evaluation:
(define (delay exp)
(lambda () exp))
(define (cons-stream a b)
(cons a
(delay b)))
With this used in cons-stream, infinite stream still illegal.
Such data structure reminds me of recursive function in whose definition self-call is legal (in compiling) within or without an actual exit.
Why is it illegal for a value to reference itself? Even the reference has been delayed?
Could infinite stream supported by other programming language?
If not, is it about the way processor deal with assembly language? The data stack stuff?
When you make a procedure the arguments are already evaluated when you start the body of the procedure. Thus delay would not do anything since it's already computed at that time. cons-stream need to be a macro.
DrRacket is not one language implementation. It's an IDE that supports lots of languages. One of them is a SICP compatibility language. I mananged to run your code without errors using this code in DrRacket:
#!planet neil/sicp
(define ones
(cons-stream 1 ones))
(define (integers-starting-from n)
(cons-stream n
(integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
It works like a charm. The default language in DrRacket, #!racket, has streams too, but the names are different:
#!racket
(define ones
(stream-cons 1 ones))
(define (integers-starting-from n)
(stream-cons n
(integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
However for Scheme you should use SRFI-41 that you can use from both #!racket (using (require srfi/41)) and #!r6rs (and R7RS-large when it's finished)
(import (rnrs)
(srfi :41))
(define ones
(stream-cons 1 ones))
(define (integers-starting-from n)
(stream-cons n
(integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
To roll your own SICP streams in both #!racket and #!r6rs you can use define-syntax
(define-syntax stream-cons
(syntax-rules ()
((_ a d) (cons a (delay d)))))
Note that RSFI-41 and rackets own stream library for #!racket delays both values in a stream-cons and not just the tail as in SICP version here.
It's because the expression in a define is evaluated before the name is bound to a value. It tries to evaluate (cons-stream 1 ones) before ones is defined, causing an error.
The reason this works fine for functions is that the body of a function is not evaluated when the function is. That is, to evaluate (lambda (x) (f x)), the language returns a function without looking at its body. Since
(define (f x) (f x))
is syntax sugar for defining a lambda, the same logic applies.
Did you define cons-stream yourself as above? If you make cons-stream a normal function it won't work properly. Since Scheme is strict by default, arguments are evaluated before the function gets called. If cons-stream is a normal function, b would get evaluated completely before being passed to delay, making you hit an infinite loop.
cons-stream in SICP is a "special form" rather than a function, which means that it can control how its arguments are evaluated.
If you use the stream-cons and other stream- operations built into Racket, you'd get the behavior you want.
Finally, some other languages do allow values to reference themselves. A great example is Haskell, where this works because everything is lazy by default. Here's a Haskell snippet defining ones to be an infinite list of ones. (Since everything is lazy, Haskell lists behave just like Scheme streams):
ones = 1 : ones
This definition works in Racket:
(define ones
(cons-stream 1 ones))
…As long as you provide a delayed implementation of cons-stream as a special form, which is the whole point of section 3.5 in SICP:
(define-syntax cons-stream
(syntax-rules ()
((_ head tail)
(cons head (delay tail)))))
Adding to the answers above, to make sure the code run, you should also define delay like this:
(define-syntax delay
(syntax-rules ()
((_ exp)
(lambda () exp))))
delay as well as cons-stream has to be defined as a macro.
In another option, you could just call the delay predefined in Racket rather than building a new one.
But don't do this:
(define (delay exp)
(lambda () exp))
The compiler would take your definition, thus the program crashes in evaluation:
Interactions disabled

Resources