# 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.

## 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 = 'P' }
{ list(i, f) for i in nums for f in fruits if f = '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 = '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.