This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
We have stumpled across some rather strange looking behaviour when trying to combine `do' and `call/cc'. I suspect the problem is related to this paragraph from R4RS: `Do' expressions are evaluated as follows: The <init> expressions are evaluated (in some unspecified order), the <variable>s are bound to fresh locations, the results of the <init> expressions ... ^^^^^^^^^^^^^^^ but if anybody can explain precisely (or even vaguely :-) what is going on in the following code, we would appreciate the enlightment. The example may seem a bit complex but has been extracted from the application we are currently working with. The idea is to control a walk of a datastructure using a kind of co-routine style to control the communication between the maintainer of the datastructure and the client doing the walk. The "server" is implemented by the following function: (define invocation-demo #f) (define scopeWalkDemo (lambda (continuation) (let ((result #f)) (set! invocation-demo (if (not continuation) (call-with-current-continuation invocation-demo) (call-with-current-continuation (lambda (found) (let ((l (list 'cow 'horse 'pig ))) (do ((i 0 (+ i 1))) ((= i (length l))) (set! result (list-ref l i)) (call-with-current-continuation found)) (set! result #f)))))) result))) which generates a list (containing the symbols cow, horse and pig) and returns these by subsequent calls of `scopeWalkDemo' as in the following session: guile> (scopeWalkDemo #t) cow guile> (scopeWalkDemo #f) horse guile> (scopeWalkDemo #f) pig guile> (scopeWalkDemo #f) #f Now, suppose I want fill the symbols into a vector using a `do' loop, I could something like this: guile> (define v-demo (make-vector 3)) guile> (do ((j 0) (cont #t) (tmp #f)) ((>= j 3)) (display (list cont j v-demo))(newline) (set! tmp (scopeWalkDemo cont)) (vector-set! v-demo j tmp) (set! j (1+ j)) (set! cont #f)) (#t 0 #(#<unspecified> #<unspecified> #<unspecified>)) (#f 1 #(cow #<unspecified> #<unspecified>)) (#f 2 #(cow horse #<unspecified>)) guile> v-demo #(cow horse pig) But if I try to update `j' using a <step> clause, I get the following: guile> (define v-demo (make-vector 3)) guile> (do ((j 0 (1+ j))(cont #t)(tmp #f)) ((>= j 3)) (display (list cont j v-demo))(newline) (set! tmp (scopeWalkDemo cont)) (vector-set! v-demo j tmp) (set! cont #f)) (#t 0 #(#<unspecified> #<unspecified> #<unspecified>)) (#f 1 #(cow #<unspecified> #<unspecified>)) (#f 1 #(horse #<unspecified> #<unspecified>)) (#f 1 #(pig #<unspecified> #<unspecified>)) (#f 1 #(#f #<unspecified> #<unspecified>)) ERROR: In expression (@call-with-current-continuation proc): ERROR: Wrong type to apply: #f ABORT: (misc-error) guile> v-demo #(#f #<unspecified> #<unspecified>) Or if I move the scopeWalkDemo into the vector-set! expression I get the following: guile> (define v-demo (make-vector 3)) guile> (do ((j 0) (cont #t)) ((>= j 3)) (display (list cont j v-demo))(newline) (vector-set! v-demo j (scopeWalkDemo cont)) (set! j (1+ j)) (set! cont #f)) (#t 0 #(#<unspecified> #<unspecified> #<unspecified>)) (#f 1 #(cow #<unspecified> #<unspecified>)) (#f 2 #(horse #<unspecified> #<unspecified>)) guile> v-demo #(pig #<unspecified> #<unspecified>) So what is going on. Is our usage of call/cc in error, is this a bug with `do' or perhaps just a feature of the excessive powers of call/cc? ---------------------------+-------------------------------------------------- Christian Lynbech | Telebit Communications A/S Fax: +45 8628 8186 | Fabrikvej 11, DK-8260 Viby J Phone: +45 8628 8177 + 28 | email: chl@tbit.dk --- URL: http://www.telebit.dk ---------------------------+-------------------------------------------------- Hit the philistines three times over the head with the Elisp reference manual. - petonic@hal.com (Michael A. Petonic)