guile-user
[Top][All Lists]

## Re: Guile Impressions

 From: Alejandro Forero Cuervo Subject: Re: Guile Impressions Date: Fri, 11 May 2001 10:22:44 -0500 User-agent: Mutt/1.2.5i

```    Have you ever had reason to use continuations in production code?

I have.  The reason has always been that they make things simpler.

I'm just going to give you an example where continuations might be
useful.  Lets say that we want to make a function that iterates on a
list of numbers adding them.  If any of the elements of the list is a
list, the function should iterate on its elements as well.  If the
function finds anything that's not a number nor a list, it should
stop and return it.

For example:

(function '(1 2 3 4))
=> 10
(function '(1 2 (1 2 3 (1 2 3 4) 4) 3 4 (1 2 3 4 (1 2 3 4))))
=> 50
(function '(1 2 a 3 4))
=> a
(function '(1 2 3 (1 2 (a) 3) b c d 4))
=> a

With continuations you can do something like the following
(Disclaimer: I'm far from being an experienced Scheme programmer so I
may be doing some things wrong here --in that case, I'd appreciate it
if others point them out):

(define (function items)
(define (loop return)
(let inner ((l items))
(cond
((null?        l ) 0)
((number? (car l)) (+        (car l)  (inner (cdr l))))
((list?   (car l)) (+ (inner (car l)) (inner (cdr l))))
(else              (return (car l))))))
(call-with-current-continuation loop))

Whenever the inner loop (`inner') finds anything that's not a number,
it calls the continuation (`return') so all the other computations
stop.

Granted, you could do this without continuations, but it would be
messier.

Another example, lets say you have an "alphabet" object that has lists
of `operations', `variables' and `values'.  And lets say you want to
make a function that searches for a symbol in those three lists in
order.  If the symbol is found on any of the lists, it is returned.
Otherwise, the function returns #f.  Lets say that to get the lists
for the "alphabet" object, one must call the alphabet:operations,
alphabet:variables and alphabet:values functions on it.  With
continuations, you could do something like:

(define (function symbol alphabet)
(define (lookup return)
(define (inner l)
(cond
((null? l)               #f)
((equal? (car l) symbol) (return symbol))
(else                    (inner (cdr l)))))
(map (lambda (l) (inner (l alphabet)))
(list alphabet:operations alphabet:variables alphabet:values))
#f)
(call-with-current-continuation lookup))

Again, you could obviously do this without continuations, but it would
be messier.  You'd need two if's or something like that.  Ok, perhaps
for this example you can find out a simple way to do things without
using continuations, but if you added more lists of things to the
"alphabet" object, I guess this version would remain simpler while
others might not.

As I see it, one of the main values of continuations is that they
allow you to jump back to one place without having to return and
return and return values.  For example, lets say you are making a big
parser that, given a long list of symbols, returns some complex
structure.  If you are using continuations, whenever you detect
something wrong in the list, you just call the continuation with some
error indicator and voila, no matter where you were on the stack, you
get back to the point where your parser was called.  If you don't use
continuations, whenever you recursively call the functions in your
parser, you have to expliclitly check and see if they return a correct
value or an error.

Alejo.
http://bachue.com/alejo

--
The mere formulation of a problem is far more essential than its solution.
-- Albert Einstein.

\$0='!/sfldbi!yjoV0msfQ!sfiupob!utvK'x44;print map{("\e[7m \e[0m",chr ord
(chop\$0)-1)[\$_].("\n")[++\$i%77]}split//,unpack'B*',pack'H*',(\$F='F'x19).
"F0F3E0607879CC1E0F0F339F3FF399C666733333CCF87F99E6133999999E67CFFCCF3".
"219CC1CCC033E7E660198CCE4E66798303873CCE60F3387\$F"#Don't you love Perl?
```

pgpVLWzZspGoF.pgp
Description: PGP signature