# Programming Language for Old Timers

by David A. Moon

February 2006 .. September 2008

Comments and criticisms to dave underscore moon atsign alum dot mit dot edu.

Previous page Table of Contents Next page

## List Comprehensions

If you like list comprehensions they are easy to implement for yourself.
Here is an example definition that uses essentially the same syntax as
Python:

defmacro \{ ?value { for ?:variable in ?list | if ?test }+ \} =>
;; wrap up nested fors and ifs
def wrapper := ``
for v in variable, l in list, t in test
if l
wrapper := `?wrapper for ?v in ?l`
else
wrapper := `?wrapper if ?t`
;; expansion does the iterations, accumulating results in a stack
`block
def result = stack()
?wrapper result.push := ?value
result.bottom-up`

Now you can write things like:

{ 2 * x for x in 0 .. 100 if x ^ 2 > 3 }
{ i for i in 0 .. 10 }
{ i for i in 0 .. 10 if i mod 2 = 0 }
;; nested iteration example
def nums = 1 .. 4
def fruits = #["Apples", "Peaches", "Pears", "Bananas"]
{ list(i, f) for i in nums for f in fruits }
{ list(i, f) for i in nums for f in fruits if f[0] = 'P' }
{ list(i, f) for i in nums for f in fruits if f[0] = 'P' if i mod 2 = 1 }

You can also define a syntax closer to standard mathematical notation allowing
you to write, for example:

{ list(i, f) | i in nums, f in fruits, f[0] = 'P', i mod 2 = 1 }

The definition of this list comprehension syntax is

defmacro \{ ?value \| { ?test [ in ?list ] & , ^^ }+ \} =>
;; wrap up nested fors and ifs
def wrapper := ``
for l in list, t in test
if l
if not t is name
error(#"invalid variable name ?t in list comprehension")
wrapper := `?wrapper for ?t in ?l`
else
wrapper := `?wrapper if ?t`
;; expansion does the iterations, accumulating results in a stack
`block
def result = stack()
?wrapper result.push := ?value
result.bottom-up`

Note the trick of parsing an iteration variable as an expression and then
reporting an error if the expression is not just a name. This makes it
possible to parse the syntax with only one-token lookahead, i.e. LL(1).

For this use of | to work, you must not import the standard | operator from
the PLOT module into your module. Or you could change the list comprehension syntax
to use : instead of |.

Alternatively you could give value the syntactic type expression-no-vbar
and define parse-expression-no-vbar as a modified copy of parse-expression
which does not recognize `|` as an infix operator. Any use of that
operator would have to be enclosed in parentheses.

Previous page Table of Contents Next page