While macro with continuations 
Author Message
 While macro with continuations

Hello all,

Sorry for the long post but here goes...

I have been looking at using a while macro recently and most times I see
people say that a while is equivalent to letrec.  From Scheme and Art of
Programming by Springer and Friedman, they say:
(while test expr1 expr2 ...)
is equivalent to:
(letrec ((loop (lambda() (if test (begin expr1 expr2 ... (loop))))))
     (loop)
)

The problem I have with this is that you are extending the environment
(which you may or may not want to do with while) and more importantly, this
can cause problems if you happen to use something called loop in your
original while statement.

ie.
(define (loop n) (< n 10))
(define x 1)
(while (loop x) (display x) (set! x (+ 1 x)))

This while is not the same as:
(letrec ((loop (lambda () (if (loop x) (begin (display x) (set! x (+ 1 x))
                             (loop))))))
     (loop)
)

So I was thinking of trying to use call-with-continuations inside the macro
expansion.  I have tried the code below in DrScheme version 101 and MIT
Scheme 7.5.9 and it seems to work but does anyone know of problems with
having call/cc in the macro expansion.  Here is my code (written to work in
DrScheme [textual MzSheme]).

(define (while-helper . express)
   (let ((condition (car express))
         (body (cons 'begin (cdr express)))
         (continue (call-with-current-continuation (lambda (x) x))))
         `(if ,condition
              ,(append body (list (list continue continue)))
              '()
          )
   )
)

Any input would be appreciated, thanks.

--
----------------------------------------------------------------------

                                    http://www.*-*-*.com/ ~dferguso



Thu, 17 Apr 2003 05:42:55 GMT  
 While macro with continuations
Oops, forgot to say that I also do:
(define-macro while while-helper)

Sorry about that.

--
----------------------------------------------------------------------

                                    http://nexus.carleton.ca/~dferguso



Thu, 17 Apr 2003 05:51:14 GMT  
 While macro with continuations
You may consider to use gensym, e.g:
(define-macro while
 (let ((loopname (gensym)))
  (lambda (test . body)

A name can be avoided by using a loop:

(define-macro while
 (lambda (test . body)

For both macros (while ...) ---> unspecified.

Jacob J. A. Koot (Jos)
http://home-1.wolmail.nl/~koot



Quote:
> Hello all,

> Sorry for the long post but here goes...

> I have been looking at using a while macro recently and most times I see
> people say that a while is equivalent to letrec.  [snip]



Fri, 18 Apr 2003 07:35:37 GMT  
 While macro with continuations

Quote:
> > I have been looking at using a while macro recently and most times I see
> > people say that a while is equivalent to letrec.  [snip]

Why not using syntax-rules ? That one describes a syntactic equivalence and
you don't have to bother with gensyms :

(require-library "synrule.ss")

(define-syntax while
  (syntax-rules ()
    ((while test e1 e2 ...)
     (letrec ((iter (lambda ()
                      (and test (begin e1 e2 ... (iter))))))
       (iter)))))

  Jean-Paul Roy



Fri, 18 Apr 2003 20:54:02 GMT  
 While macro with continuations


Quote:
> I have been looking at using a while macro recently and most times I
> see people say that a while is equivalent to letrec.  From Scheme and
> Art of Programming by Springer and Friedman, they say:
> (while test expr1 expr2 ...)
> is equivalent to:
> (letrec ((loop (lambda() (if test (begin expr1 expr2 ... (loop))))))
>      (loop)
> )

> The problem I have with this is that you are extending the environment
> (which you may or may not want to do with while) and more importantly,
> this can cause problems if you happen to use something called loop in
> your original while statement.

There is a way to implement 'while' without introducing any bindings
in the scope of the test expression or the body. No extra bindings at
all -- for gensym-variables or otherwise. It appears that's what the
original author wanted.

The implementation is based on the following transformation:
 (while test body)
 =====>
(
 (lambda (test-thunk body-thunk)
   (letrec
     ((loop (lambda ()
               (if (test-thunk) (begin (body-thunk) (loop))))))
     (loop)))
 (lambda () test)    ; test-thunk
 (lambda () body)    ; body-thunk
)

This implementation can be generalized so that (while test body)
returns the result of the last evaluation of the body, or #f

(
 (lambda (test-thunk body-thunk)
   (letrec
     ((loop (lambda (prev-result)
               (if (test-thunk) (loop (body-thunk)) prev-result))))
     (loop #f)))
 (lambda () test)    ; test-thunk
 (lambda () body)    ; body-thunk
)

The following macro implements this construction:
(define-macro (while test body1 . bodyrest)
 `(
   (lambda (test-thunk body-thunk)
    (letrec
      ((loop (lambda (prev-result)
               (if (test-thunk) (loop (body-thunk)) prev-result))))
      (loop #f)))
  (lambda () ,test)             ; test-thunk

))

The macro does not introduce any binding in the scope of its argument
expressions. Therefore, the macro is hygienic by construction.

(let ((i 0) (j 0))
 (while (< i 2) (display i) (display ": ")
   (display
    (while (< j i) (display j) (display " ") (set! j (+ 1 j)) j))
   (newline) (set! i (+ 1 i))))
==prints==>
0: #f
1: 0 1

We can even avoid any binding construction whatsoever save lambda:
 (while test body)
 =====>
(
 (
   (lambda (f)
     (f f))             ; The U combinator
    (
      (lambda (test-thunk body-thunk)  ; The "While combinator"
        (lambda (self)
          (lambda (prev-value)
            (if (test-thunk) ((self self) (body-thunk)) prev-value))))
       (lambda () test)                 ; test-thunk
       (lambda () body)                 ; body-thunk
    )
  )
  #f                    ; Initial value for prev-value
)

This is an example of programming with combinators. It's well known
that combinatorial logic avoids any (visible) variables. It follows
then that macros in the combinational style are hygienic by
construction. Hmm, another solution to the hygiene problem?

Sent via Deja.com http://www.deja.com/
Before you buy.



Tue, 22 Apr 2003 08:12:18 GMT  
 While macro with continuations

Quote:

> There is a way to implement 'while' without introducing any bindings
> in the scope of the test expression or the body. No extra bindings at
> all -- for gensym-variables or otherwise. It appears that's what the
> original author wanted.

That was what I was looking for.  Thanks to everyone who gave input.

--
----------------------------------------------------------------------

                                    http://nexus.carleton.ca/~dferguso



Wed, 23 Apr 2003 00:34:49 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. A macro involving two sub-macros - where the 2nd macro needs results from the first

2. macro -vs- macro/codeblock

3. Help with macros writing macros in Bigloo

4. syntax-rules macros with sub-macros

5. Scheme macro source: rewriter-widget, a widely applicable macro interface

6. Macros defining macros with define-syntax

7. symbol-macros and regular macros

8. Question about a macro-defining macro

9. Macro-Defining Macros

10. macro macros

11. Local macro within a macro?

12. how much macro is too much macro

 

 
Powered by phpBB® Forum Software