> < ^ From:

^ Subject:

Sebastian Egner wrote in his mail message of 1996/03/23

being an enthusiastic GAP user and programmer, I have collected two

suggestions on improving the GAP language itself. Although I appreciate

the idea of `lean' languages, as for example GAP is, it seems to me that

GAP might benefit from these additions. Especially ZF-comprehensions

turned out to be so useful in other languages I used before (Gofer,

Haskell) that I would be very glad to have it in GAP, too. In case these

ideas fit the general design considerations and development strategy of

the GAP-project I would like to do actual implementation work on it.

Thank you very much for your suggestions and your offer to help us

implement them.

Iterators will be supported in the next version of GAP. The names

and semantics will be very similar to the ones you suggest.

I also like list comprehensions very much. They are especially useful

for interactive use (but I don't use them often in my programs).

However comprehensions with the syntax you describe require major changes

to the parser. In particular they require unbounded lookahead (whether a

variable in the expression refers to an outer variable or a loop variable

cannot be decided before the entire comprehension has been parsed).

I think that a small change to 'List', 'Set' are almost as good. Allow

me to describe them (using 'List' as example).

'List' would take 2 or more arguments. Every argument but the last can be

1) a list or a domain (to introduces a new loop variable),

2) a function returning a list or a domain (to have the elements to loop

over depend on the values of the outer loop variables),

3) a function returning 'true' or 'false' (to filter).

The last argument must be function, which is applied to the values of

the loop variables and whose results are collected.

Understanding this function is probably much easier by examples than from

a formal definition. So here is how your first example

[ x^2 | for x in [100, 99 .. 1], IsPrime(x) ] # comprehension

can be expressed using this extended 'List'

List( [100, 99 .. 1], x -> IsPrime(x), x -> x^2 ) # GAP

or since 'x -> IsPrime(x)' is equivalent to 'IsPrime'

List( [100, 99 .. 1], IsPrime, x -> x^2 ) # GAP

(which is even shorted than the comprehension).

And your second example

{ [n, r] | for n in [1..10], for r in PrimeResidues(n) } # comprehension

can be written as follows

Set( [1..10], n->PrimeResidues(n), function(n,r) return [n,r] end ) # GAP

Of course it would be nice to have a short notation for functions of more

than one argument, so that the latter can be written as

Set( [1..10], n -> PrimeResidues(n), (n,r) -> [n,r] )

Using the function 'ListArgs', which simply returns the list of its

arguments (i.e., 'ListArgs := function ( args ) return args; end;'),

we can express the last examples as follows

Set( [1..10], PrimeResidues, ListArgs ) # GAP

(which is pretty short, but not so easy to read).

One nice thing is that it is easy to generalize 'Sum' and 'Product'

likewise. With comprehensions you would either have to create the entire

list and sum afterwards or come up with yet another syntactic extension.

Kindly, Martin.

-- .- .-. - .. -. .-.. --- ...- . ... .- -. -. .. -.- .- Martin Sch"onert, Martin.Schoenert@Math.RWTH-Aachen.DE, +49 241 804551 Lehrstuhl D f"ur Mathematik, Templergraben 64, RWTH, 52056 Aachen, Germany

> < [top]