communicating with programs
The most naive way to interact with another program is simply to run
it, let it communicate directly with the user, and wait for it to
finish. This is done with the run command.
i1 : run "uname -a"
Linux geometry 2.1.128 #53 SMP Sat Nov 14 08:34:06 CST 1998 i586
o1 = 0 |
More often, one wants to write Macaulay 2 code to obtain
and manipulate the output from the other program. If the program
requires no input data from us, as in the example above, then we can
use get with a file name whose first character is an
exclamation point; the rest of the file name will be taken as the
command to run. In this example, we also peek at the string
to see whether it includes a newline character.
i2 : peek get "!uname -a"
o2 = "Linux geometry 2.1.128 #53 SMP Sat Nov 14 08:34:06 CST 1998 i586\n"
o2 : String |
We can even use this method to call upon Macaulay 2 itself for a
computation, putting the computational request into the command line.
We could then use value to convert the string returned to
a number.
i3 : g = get "!M2 -q -silent -e'<< 2^100' -e'exit 0'"
o3 = 1267650600228229401496703205376
o3 : String |
i4 : peek g
o4 = "1267650600228229401496703205376"
o4 : String |
i5 : value g
o5 = 1267650600228229401496703205376 |
Bidirectional communication with a program is also possible. We use
openInOut to create a file that serves as a bidirectional
connection to a program. That file is called an input output file. In
this example we open a connection to the unix utility egrep
and use it to locate the symbol names in Macaulay2 that begin with
in.
i6 : f = openInOut "!egrep '^in'"
o6 = --input output file !egrep '^in'--
o6 : File |
i7 : scan(keys symbolTable(), key -> f << key << endl) |
i8 : f << closeOut
o8 = --input file !egrep '^in'--
o8 : File |
i9 : stack sort lines read f
o9 = incomparable
indeterminate
index
indexComponents
indices
inducedMap
inducesWellDefinedMap
infinity
input
installMethod
instance
integrate
intersect
o9 : Net |
i10 : close f
o10 = --closed file--
o10 : File |
With this form of bidirectional communication there is always a danger
of blocking, because the buffers associated with the communication
channels (pipes) typically hold only 4096 bytes. In this example we
succeeded because the entire output from egrep was smaller
than 4096 bytes. In general, one should be careful to arrange things
so that the two programs take turns using the communication channel, so
that when one is writing data, the other is reading it.
A useful function in this connection is isReady which will
tell you whether an input file has any input available for reading, or
whether it has arrived at the end. We illustrate it in the following
example by simulating a computation that takes 5 seconds to complete,
printing one dot per second while waiting.
i11 : f = openIn "!sleep 5; echo -n the answer is 4"
o11 = --input file !sleep 5; echo -n the answer is 4--
o11 : File |
i12 : isReady f
o12 = false |
i13 : while not isReady f do (sleep 1; << "." << flush)
...... |
i14 : read f
o14 = the answer is 4
o14 : String |
i15 : isReady f
o15 = true |
i16 : atEndOfFile f
o16 = true |
i17 : close f
o17 = --closed file--
o17 : File |
We also allow for bidirectional communication
through sockets over the internet. See openInOut
and openListener, or the next section.
Another useful function is wait, which can be used
to wait for input to be available from any of a list of input
files.



