> < ^ Date: Fri, 25 Mar 1994 11:03:00 +0100
> < ^ From: Martin Schoenert <martin.schoenert@math.rwth-aachen.de >
< ^ Subject: Re: AppendTo

Erik Roijackers writes in his e-mail message of 1994/03/23

To be able to call an external executable, it's necessary to write
information to a file. As far as I know, GAP offers the functions
PrintTo and AppendTo. These functions both open a file, write the
information and close it again (am I right?) So when the function
AppendTo is used within a loop, writing in each cycle a small amount
of information, the file is opened and closed again very often,
consuming a huge amount of time.

This is correct. It is just barely tolerable under UNIX. Under TOS (on
the Atari ST), it was impossible, because seeking to the end of the file
took time proportional to the size of a file. So writing a file with <n>
lines took time <n>^2. I don't now whether this is true under DOS.

He continues

Is there a way to open a file once, write all the information using
a loop, and close it again?

Hmm, yes and no. In C you open a file, obtain a file pointer, and then
use this to write to the file. Something like this is not possible in
GAP. That means you *cannot* write something like

file := OutputFile( "erwin" );
for i  in [1..100]  do
    PrintTo( file, Size( group[i] ), "\n" );
od;
CloseFile( file );

We plan something like this, but not for the immediate future.

But there is a hack, which may solve your problem. What you can do, is
to put your loop in a simple function. Then you call this function
from 'PrintTo'. I.e., do the following

Dummy := function ()
    for i  in [1..100]  do
        Print( Size( group[i] ), "\n" );
    od;
end;
PrintTo( "erwin", Dummy() );

This makes use of the fact that when the arguments to 'PrintTo' are
evaluated the current output file is the one opened by 'PrintTo', so
everything that would usually go to '*stdout*' (i.e., the screen) is
written to the file.

This doesn't solve all problems, because you cannot interact with GAP
while the output is computed and written to the file, but in many cases
this is sufficient.

He continues

I have thought of using strings. First, all the information is stored
in a string (using Concatenation), after which the whole string is
written to a file using PrintTo. It turns out that, at least when
working under DOS, this is even slower than the first option.

In GAP 3.3 'Concatenation' has a ``small'' problem. It creates the
output list as a list of characters (with each character taking 4 bytes)
instead of as a string. So the reason why this is slower is probably
because the string becomes so large that GAP has to do many garbage
collections.

You might want to try something like the following code.

cache := "";
for i  in [1..100]  do
    Append( cache, String( Size( group[i] ) ), "\n" );
    if 8192 < Length(cache)  then
        AppendTo( "erwin", cache );
        cache := "";
    fi;
od;

Hope this helps, 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]