Friday, August 13, 2010

while/until in scheme

I don't really to pervert language philosophies. Scheme is a functional language, and I like to use it as such.
However, Scheme is not a pure functional language and has all the state changing features one would expect from an imperative language (e.g., set!).

The idea here is not new nor a good one: we are to define a while form. Of course, you have to manually modify the looping variables in the while body. As you would in C. Besides, this was one of my first attempts at not completely trivial macros in scheme.

Here we are using scheme hygienic macros, and in particular the syntax-rules variant, which is standard in R5RS and R6RS. There are other systems, but as far as I know none of them is completely standard.

Here we are essentially saying: if you find a while "function", treat it like in a special way.
Don't loop for the "while" function, but transform the s-expression in the way specified in the second s-expression inside the square brackets.

(define-syntax while
  (syntax-rules ()
    [(_ c b1 b2 ...)
     (let loop ()
       (when c b1 b2 ... (loop)))]))

(define-syntax until
  (syntax-rules ()
    [(_ c b1 b2 ...) (while (not c) b1 b2 ...)]))

And now you can write ugly stuff like:

(define-syntax while
(let ([i 10]) 
  (until (zero? i) 
         (displayln i) 
         (set! i (- i 1))))

My scheme has no when!


If your scheme has no when/until forms, they can be easily defined with:
(define-syntax when
  (syntax-rules ()
    [(_ c b1 ...)
     (cond (c b1 ...) (else #f))]))

(define-syntax unless
  (syntax-rules ()
    [(_ c b1 ...)
     (cond (c #f) (else b1 ...))]))

No comments: