> < ^ Date: Thu, 20 Aug 1992 15:59:07 +0200
> < ^ From: Martin Schoenert <martin.schoenert@math.rwth-aachen.de >
> < ^ Subject: Re: Various suggestions

Please ignore my previous post, I accidently mailed it before it was
complete. [Previous post removed from archive]

Quite a while ago Steve Linton made various suggestions. I want to make
some remarks. Generally most of them seem reasonable. However, please
don't expect those feature to show up in the next release.

Steve write:

It would be nice to be able to access the operating system
environment from GAP. A function Getenv(string) perhaps and/or an
array Environment of pairs of strings.

What about a record? 'ENVIRONMENT.USER' would evaluate to '"sl25"'.
Actually a function like 'Getenv' is probably safer, because I am not
certain that all systems support 'environ'. Anybody knows what ANSI has
to say about this?

Steve continues:

It would be nice to have a structure that behaved like a hash-table
or a PERL associative array. This would enable general Orbit
algorithms to go MUCH faster. More generally Aho, Hopcraft and Ulmann
(Design and Analysis...) has a nice general description of
'dictionaries' in terms of which operations can be carried out
quickly. A set of constructs implementing these would be extremely

This is clearly the most ambitious suggestion. I agree that hash-tables
or associative arrays would be very nice. What I would really like to
have in GAP are *tables*, which are basically mappings from arbitrary
keys to values. A table where all keys are positive integers is a list,
a table where all keys are strings is a record. Very elegant, very

The problem is the implementation. In GAP 2.4 we used hashing for sets.
We had problems to come up with a reasonable hash function that worked
well for all possible keys.

Such a hash function would have to look at all the bytes of an object to
compute the hash value. To see this imagine a hash function that only
looks at the first 32 bytes of an object. If this hash function is used
on a list of permutations that all lie in the stabilizer of [1..16] it
would hash all to the same value.

On the other hand look at the following rather common case. Suppose we
have a list of 1000 permutations of degree 1000 and suppose that [1..5]
is a base, e.g., no two permutations map [1..5] to the same images. Then
the binary search does 10 comparisons of permutations, and for each
comparison of permutations it compares at most 5 images. So it looks at
10 * 5 * 2 = 100 numbers. But the hash function must look at all 1000
numbers of the permutations that is looked up. So the binary search is
actually faster in this case.

Another problem with hash functions is that there are objects in GAP that
are equal, but are represented differently. So the hash function cannot
simply be a function of the representation (i.e. of the sequence of bytes
used to represent an object).

This is not to say that tables could not be made to work efficiently.
However, clearly this area needs more investigation. Maybe we can learn
more from the Maple people; Maple uses hashing all the time.

Steve continues:

Especially on PCs (I don't know about STs) repeated use of AppendTo
is very slow as the file has to be closed and the directory updated
between each call. It would be nice to have fopen, fread/write and
fclose -like calls using some sort of file handle.

There will be better support for I/O when GAP finally gets the
facilities to communicate with subprocesses. This will also solve
this problem (and some others as well). This will be some Scheme
stream like facility (instead of C like handles).

Steve continues:

It would be nice to be able to control the level of printing when
entering a break loop. When the progran is in a recursive procedure
or something I often loose the piece of information I want off the
end of the traceback.

I am not certain that I understand this request. Doesn't 'Backtrace'
do what you want? Umm, I see now. 'Backtrace' is not documented.
Ok, here is a description of 'Backtrace'. Hope this helps.

'Backtrace( <level> )'

'Backtrace' can be used inside a break loop to print a history of the
computation. 'Backtrace' prints a list of all active functions, most
recent first, up to maximal <level> nestings. If <level> is positive
the *expressions* of the arguments of the functions calls are printed,
otherwise the *values* of the actual arguments are printed instead.
<level> default to 5, i.e., calling 'Backtrace' with no argument will
print the 5 most recent functions with the expressions of the arguments.

When a break loop (see "Break Loops") is entered 'Backtrace' is called

Steve continues:

Also for debugging purposes, it would be nice to be able to look past
a local variable at a 'hidden' variable of the same name in an outer
scope. Either some way of saying 'The global x' and the 'the x
belonging to procedure foobar' (though what happens if foobar is
recursed 8 levels deep?) or of saying 'The x in the scope outside
this one'.

There will be functions 'NextEnvironment' and 'PrevEnvironment',
which will allow you to step up and down the stack. Each local variable
will then be searched on that level. So to find 'foobar' 8 levels deep
you write 'NextEnvironment(8); foobar; PrevEnvironment(8);'.

Steve continues:

Possibly the read-eval-print loop should suppress or abbreviate the
printing of very long results.

Could you elaborate this a little bit more? On what should it depend
whether GAP suppresses the output? Do you want GAP to detect that the
output is going to be longer than 300 lines, and suppress it?


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

> < [top]