13.2. Using C Functions in Swarm

The fundamental rules of C programming apply in Swarm. Perhaps most importantly:

If a function is defined at the top of a source code file--after the includes and imports but before the implemenation line, then that function can be called anywhere in that file. If the function is not used in any other files, then there is no need to put a prototype for it in the header file and the declaration of the function should start with "static".

A function can also be defined inside a method!. It looks a bit peculiar when functions crop up inside Objective C methods, but there is nothing wrong with doing so. Of course, when a function is defined inside a method, then its scope is sharply restricted. That function can be called only inside that method.

There are some occasions in which is is extremely handy to define functions inside methods. Two particulary useful aspects of this practice are as follows. First, Objective C calls to self can be made in such functions. If a function needs some value, and it intends to get it by calling a get method such as [self getThatNumber] it will work as long as the function is defined inside a legitimate Objective C method. If the function is located at the top of the file, before the implementation statement, then the term self will have no meaning and the program will not compile.

The second useful aspect is of this practice is that one can have several different functions with the same name if those functions are set inside Objective C methods. It may seem hard to imagine situations in which this would be useful, but they do arise.

Suppose inside a class there are two methods and each makes use of a function from the standard C libraries. If the function expects to have some other user-defined function available when it is run, then the user can customize that user-defined function inside each method. To be a bit more concrete, consider the GNU C library's binary search tree defined in the header file search.h. The function tsearch (version 2.1) has this prototype:

void * tsearch(const void *key, void ** rootp, int (*compar) (const void *, const void *) );

The tsearch function checks to see if a node already exists by using a comparison function. If an equal node exists, then tsearch returns that node. If no such node exists, tsearch adds the node to the tree. Note that the comparision function used in the tsearch must be included as the last argument.

The problem may arise that one wants to use different comparison functions when working with a single tree. Once a tree is created with a comparison function called compare_node, then all calls on the tree must use a comparison function with the same name. Perhaps there is some slight wrinkle to be introduced when deciding whether one node is equal to another when they are being inserted and when they are being printed out or removed. By defining several compare functions, one inside each method that makes use of the tree, one can acheive the desired level of specialization.