Writing Python in Scheme

Python was the first language I learned (second if you count QBasic, and I don’t). Like the classic Fortran programmer who can write Fortran in any language, I have often found myself instinctively writing my Lisp programs with a distinctly Pythonic flavor. To get it out of my system, here are a few simple macros to recreate Python loops in Scheme. This is not serious and should not be seriously used. It’s just a bit of fun!

First, I recreated the beloved Python for loop. Lispers insist that Python’s for is just syntactic sugar for map, but I find that Python style for loops often express themselves less succinctly as map calls.

(define-syntax-rule (for i in lst body ...)
  (map (lambda (x) 
         (let ((i x)) (begin body ...))) 
       lst))

 
And here is how it works when you call it:

(define a 0)

(for i in (range 3)
  (set! a (+ a i))
  (print a))

Output: 136

 
The cool thing about that macro is that it returns a list of the value of each iteration. This allows us to easily emulate Python’s list comprehensions as well, like so:

> (for i in (range 3)
    (number->string (+ i 1)))
'("1" "2" "3")

 
To appreciate the elegance of that macro, here is the same code using a traditional call to map:

(map (lambda (x) 
       (number->string (+ x 1))) 
     (range 3))

 
Maybe I am just biased, but the Pythonic style just seems more clear. Anyway, let’s do one more loop – the while loop. The while loop has been implemented thousands of different ways in Scheme, but we want to mimic the Python while loop as much as possible, so we will use the following macro:

(define-syntax-rule (while condition body ...)
  (let loop ((iter-vals null))
    (if condition
        (loop (append iter-vals (list (begin body ...))))
        iter-vals)))

 
Here is our macro being used:

(define p 0)

(while (< p 5)
  (set! p (+ p 1))
  (print p))

Output: 12345

 
Interestingly, because this macro is so similar to our for loop, we can even use comprehensions with it, like this:

> (while (< p 5) (set! p (+ p 1)) (* p 10))
'(10 20 30 40 50)

 
Scheme is such a wonderfully expressive language that recreating your favorite features from other languages is extremely easy, although I recommend against it. If you want to program in every language simultaneously learn C++. For the rest of us, source code is already obfuscated enough. That’s enough fun for now. Time to figure out what I was actually working on before I got distracted by this!

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*