|
3.8.6 Procedures in a library
Here asre hints and requirements on how procedures contained in a
library should be implemented. For more on procedures,
see Procedures.
-
Each procedure not meant to be accessible by users should be declared static.
-
The header of each procedure not declared static must comply with the guidelines
described in Procedure definition and Help string.
In particular, it must have a help and example section, and assumptions made
should be carefully explained. If the assumptions are checked by the procedure
on run-time, errors may be reported using the ERROR function.
-
Names of procedures should not be shorter than 4 characters and should not
contain any special characters. In particular, the use of
_ in names of
procedures is discouraged. If the name of the procedure is composed of
more than one word, each new word should start with a capital letter, all
other letters should be lower case (e.g. linearMapKernel).
-
No procedures should be defined within the body of another procedure.
-
A procedure may print out comments, for instance to explain results or to
display intermediate computations. This is often helpful when calling the
procedure directly, but it may also cause confusions in cases where the
procedure is called by another procedure. The SINGULAR solution to
this problem makes use of the function
dbprint (see dbprint)
and the reserved variables printlevel and voice
(see printlevel and see voice). Note that printlevel is a
predefined, global variable whose value can be changed by the user, while
voice is an internal variable, representing the nesting level of
procedures. Accordingly, the value of voice is 1 on the top level,
2 inside the first procedure, and so on. The default value of
printlevel is 0, but printlevel can be set to
any integer value by the user.
- Example:
- If the procedure
Test below is called directly from
the top level, then `comment1' is displayed, but not `comment2'.
By default, nothing is displayed if Test is called from within any
other procedure. However, if printlevel is set to a value k
with k>0, then `comment1' (resp. `comment2') is displayed -- provided
Test is called from another procedure with nesting level at
most k (resp. k-1).
The example part of a procedure behaves in this respect like the
procedure on top level (the nesting level is 1, that is, the value of
voice is 2). Therefore, due to the command printlevel=1; ,
`comment1' will be displayed when entering example Test; .
However, since printlevel is a global variable, it should be reset to
its old value at the end of the example part.
The predefined variable echo controls whether input lines are
echoed or not. Its default is 0, but it can be reset by the user. Input
is echoed if echo>=voice . At the beginning of the example
part, echo is set to the value 2. In this way, the input lines
of the example will be displayed when entering example Test; .
| proc Test
"USAGE: ...
...
EXAMPLE: example Test; shows an example
"
{ ...
int p = printlevel - voice + 3;
...
dbprint(p,"comment1");
dbprint(p-1,"comment2");
// dbprint prints only if p > 0
...
}
example
{ "EXAMPLE:"; echo = 2;
int p = printlevel; //store old value of printlevel
printlevel = 1; //assign new value to printlevel
...
Test();
printlevel = p; //reset printlevel to old value
}
|
- Note:
- SINGULAR functions such as
pause or read allow
and require interactive user-input. They are, thus, in particular useful
for debugging purposes. If such a command is used inside the procedure
of a library to be distributed with SINGULAR, the example section of
the procedure has to be written with some care -- the procedure should
only be called from within the example if the value of printlevel
is 0. Otherwise, the automatic build process of SINGULAR will not
run through since the examples are carried out during the build process.
They are, thus, tested against changes in the code.
|