Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Python 'for' as Scheme 'let'

5 views
Skip to first unread message

ol...@pobox.com

unread,
Feb 13, 2004, 9:19:06 PM2/13/04
to
We show that the 'for' operator of Python quite unexpectedly
can be represented by a 'let' form of Scheme.

What looks in Python like
for k in range(1,4):
print k

looks in Scheme as

(breset r
(let ((k (range r 1 4)))
(display k) (newline)
))


This iteration construct uncannily resembles Python. It nests and
supports the premature termination and skipping of iterations at any
level. We should also emphasize that no intermediate lists are
constructed!

The 'let' in the above code is the ordinary Scheme let. The macro range
has been described in the article:

http://google.com/groups?selm=7eb8ac3e.0312172046.6d817907%40posting.google.com

The macro range was actually designed to emulate 'range' of Matlab and
Octave. The fact it turns out so useful to emulate Python loops was
a pleasant surprise.

All the code in this article should be considered a continuation of
that in the quoted article. It is tested on Petite Chez Scheme,
Gauche, Bigloo, Scheme48, and SCM.


When we run

(breset r
(let ((k (range r 1 4)))
(display k) (newline)
))

we see the numbers 1 through 4 printed (in Matlab/Octave and our
range, the range is inclusive).

We can do more complex things:

(breset r
(let* ((k (range r 1 3 9))
(j (+ 10 k)))
(display j) (newline)
))

which prints the numbers 11, 14, and 17

We can terminate iterations early:

(breset out (breset r
(let ((k (range r 1 4)))
(display k) (newline)
(if (> k 2) (bshift out f #f))
)))
which prints only 1, 2, and 3

or we can skip the iterations (like C's continue)

(breset r
(let ((k (range r 1 4)))
(if (odd? k) (bshift r f #f))
(display k) (newline)
))

which prints only 2 and 4.

We can do nested loops:

(breset r
(let ((k (range r 1 4)))
(breset inner
(let ((j (range inner 10 k (* 10 k))))
(display (list k j)) (newline)
))))

as you can see, the boundaries and the step of the inner loop depends
on the variable of the outer loop.

We can also skip the iteration of the outer loop in the inner loop!
C can't do that.

(breset r
(let ((k (range r 1 4)))
(breset inner
(let ((j (range inner 10 k (* 10 k))))
(if (odd? k) (bshift r f #f)) ; continues the outer! loop
(display (list k j)) (newline)
))))

The naming of the loop variable is by no means mandatory. The
following works the same as the last-but-one example.

(breset r
(let ((k (range r 1 4)))
(breset inner
(begin
(display (list k (range inner 10 k (* 10 k))))
(newline)))))
It prints:
(1 10)
(2 10)
(2 12)
(2 14)
(2 16)
(2 18)
(2 20)
(3 10)
(3 13)

etc.
This code doesn't seem to have a direct correspondence in C. There are
no intermediate lists constructed. One can see that from the fact that
the newline is printed after _each_ set of numbers.

0 new messages