Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 uid=99(nobody) gid=98(nobody) groups=98(nobody) Safe-mode: OFF (not secure) /usr/doc/slang-1.4.5/html/ drwxr-xr-x | |
| Viewing file: Select action/file-type: 9. Functions
A function may be thought of as a group of statements that work together to perform a computation. While there are no imposed limits upon the number statements that may occur within a function, it is considered poor programming practice if a function contains many statements. This notion stems from the belief that a function should have a simple, well defined purpose.
9.1 Declaring Functions
Like variables, functions must be declared before they can be used. The
is sufficient to declare a function named factorial. Unlike
the variable keyword used for declaring variables, the
define keyword does not accept a list of names.
Usually, the above form is used only for recursive functions. In most cases, the function name is almost always followed by a parameter list and the body of the function:
The function-name is an identifier and must conform to the
naming scheme for identifiers discussed in chapter ???.
The parameter-list is a comma-separated list of variable names
that represent parameters passed to the function, and
may be empty if no parameters are to be passed.
The body of the function is enclosed in braces and consists of zero
or more statements (statement-list).
The variables in the parameter-list are implicitly declared, thus, there is no need to declare them via a variable declaration statement. In fact any attempt to do so will result in a syntax error.
9.2 Parameter Passing Mechanism
Parameters to a function are always passed by value and never by reference. To see what this means, consider
Here a function add_10 has been defined, which when executed,
adds 10 to its parameter. A variable b has also been
declared and initialized to zero before it is passed to
add_10. What will be the value of b after the call to
add_10? If S-Lang were a language that passed parameters by
reference, the value of b would be changed to
10. However, S-Lang always passes by value, which means that
b would retain its value of zero after the function call.
S-Lang does provide a mechanism for simulating pass by reference via the reference operator. See the next section for more details. If a function is called with a parameter in the parameter list
omitted, the corresponding variable in the function will be set to
This function must be called with two parameters. However, we can
omit one or both of the parameters by calling it in one of the
following ways:
The first example calls the function using both parameters;
however, at least one of the parameters was omitted in the other
examples. The interpreter will implicitly convert the last three
examples to
It is important to note that this mechanism is available only for
function calls that specify more than one parameter. That is,
is not equivalent to add_10(NULL). The reason for this
is simple: the parser can only tell whether or not NULL should
be substituted by looking at the position of the comma character in
the parameter list, and only function calls that indicate more than
one parameter will use a comma. A mechanism for handling single
parameter function calls is described in the next section.
9.3 Referencing Variables
One can achieve the effect of passing by reference by using the
reference (
The expression &b creates a reference to the variable
b and it is the reference that gets passed to add_10.
When the function add_10 is called, the value of a will
be a reference to b. It is only by dereferencing this
value that b can be accessed and changed. So, the statement
@a=@a+10; should be read `add 10' to the value of the
object that a references and assign the result to the object
that a references.
The reader familiar with C will note the similarity between references in S-Lang and pointers in C. One of the main purposes for references is that this mechanism allows reference to functions to be passed to other functions. As a simple example from elementary calculus, consider the following function which returns an approximation to the derivative of another function at a specified point:
It can be used to differentiate the function
at the point x = 3 via the expression
derivative(&x_squared,3).
9.4 Functions with a Variable Number of Arguments
S-Lang functions may be defined to take a variable number of arguments. The reason for this is that the calling routine pushes the arguments onto the stack before making a function call, and it is up to the called function to pop the values off the stack and make assignments to the variables in the parameter list. These details are, for the most part, hidden from the programmer. However, they are important when a variable number of arguments are passed. Consider the
For the uninitiated, this example looks as if it
is destined for disaster. The add_10 function looks like it
accepts zero arguments, yet it was called with a single argument.
On top of that, the assignment to x looks strange. The truth
is, the code presented in this example makes perfect sense, once you
realize what is happening.
First, consider what happened when A generic function of the form
is internally transformed by the interpreter to
before further parsing. (The add_10 function, as defined above, is
already in this form.) With this knowledge in hand, one can write a
function that accepts a variable number of arguments. Consider the
function:
Here, the last argument passed to average_n is an integer
reflecting the number of quantities to be averaged. Although this
example works fine, its principal limitation is obvious: it only
supports one or two values. Extending it to three or more values
by adding more else if constructs is rather straightforward but
hardly worth the effort. There must be a better way, and there is:
The principal limitation of this approach is that one must still
pass an integer that specifies how many values are to be averaged.
Fortunately, a special variable exists that is local to every function
and contains the number of values that were passed to the function.
That variable has the name
Here, if no arguments are passed to the function, a simple message
that indicates how it is to be used is printed out.
9.5 Returning Values
As stated earlier, the usual way to return values from a function
is via the
where expression-list is a comma separated list of expressions.
If the function does not return any values, the expression list
will be empty. As an example of a function that can return
multiple values, consider
which is a function returning two values.
It is extremely important to note that the calling routine must explicitly handle all values returned by a function. Although some languages such as C do not have this restriction, S-Lang does and it is a direct result of a S-Lang function's ability to return many values and accept a variable number of parameters. Examples of properly handling the above function include
See the section below on assignment statements for more information
about this important point.
9.6 Multiple Assignment Statement
S-Lang functions can return more than one value, e.g.,
returns two values. It accomplishes this by placing both values on
the stack before returning. If you understand how S-Lang functions
handle a variable number of parameters (section ???), then it
should be rather obvious that one assigns such values to variables.
One way is to use, e.g.,
However, the most convenient way to accomplish this is to use a multiple assignment statement such as
The most general form of the multiple assignment statement is
In fact, internally the interpreter transforms this statement into
the form
for further processing.
If you do not care about one of return values, simply omit the variable name from the list. For example,
assigns the sum of 9 and 4 to s and the
difference (9-4) will be removed from the stack.
As another example, the jed editor provides a function called
it is more convenient to use a multiple assignment expression and
omit the variable name, e.g.,
Some functions return a variable number of values instead of a fixed number. Usually, the value at the top of the stack will indicate the actual number of return values. For such functions, the multiple assignment statement cannot directly be used. To see how such functions can be dealt with, consider the following function:
This function returns either one or two values, depending upon the
return value of fgets. Such a function may be handled as in
the following example:
In this example, the last value returned by read_line is
assigned to status and then tested. If it is non-zero, the
second return value is assigned to s. In particular note the
empty set of parenthesis in the assignment to s. This simply
indicates that whatever is on the top of the stack when the
statement is executed will be assigned to s.
Before leaving this section it is important to reiterate the fact
that if a function returns a value, the caller must deal with that
return value. Otherwise, the value will continue to live onto the
stack and may eventually lead to a stack overflow error.
Failing to handle the return value of a function is the
most common mistake that inexperienced S-Lang programmers make.
For example, the
as one could in C, a S-Lang programmer should write
in S-Lang. (Many good C programmer's write (void)fflush(fp)
to indicate that the return value is being ignored).
9.7 Exit-Blocks
An exit-block is a set of statements that get executed when a
functions returns. They are very useful for cleaning up when a
function returns via an explicit call to An exit-block is created by using the
where statement-list represents the list of statements that
comprise the exit-block. The following example illustrates the use
of an exit-block:
Here, the function contains an exit-block and a forever loop.
The loop will terminate via the return statement when n
is 10. Before it returns, the exit-block will get executed.
A function can contain multiple exit-blocks, but only the last one encountered during execution will actually get executed. For example,
If 1 is passed to this function, the first exit-block will
get executed because the second one would not have been encountered
during the execution. However, if some other value is passed, the
second exit-block would get executed. This example also
illustrates that it is possible to explicitly return from an
exit-block, although nested exit-blocks are illegal.
Next Previous Contents |
:: Command execute :: | |
--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0045 ]-- |