## Friday, October 14, 2011

### Scilab Functions - Counting Arguments

Counting the number of input and output arguments for a Scilab function call at run time can simulate default input arguments and avoid computing those output arguments that are not required.
Parameters are the variable you use to define the input to and output from a function at the time of its definition. They help the programmer refer to pieces of data while developing the function without having to think about how the function will be used, which will happen only later, after the function is completed and put to use. When the function is put to use by calling (or invoking it) from within a parent function, parent function passes in data to the child function (input arguments) and retrieves the data returned by the function (output arguments).

This is true of almost all programming languages, although there may be slight variations on this basic scheme. Thus arguments are data when the function is invoked and parameters are data used when the function is defined. Let us consider the example in the previous post on this blog:

function [L] = linelen(p1, p2)
L = sqrt(sum((p2 - p1).^2))
endfunction

In the function definition above, p1 and p2 are input parameters that the function uses as input to calculate the output parameter L, namely the length of the line joining the points p1 and p2. Let us modify this function so that it returns another output parameter dc, a vector of the direction cosines of the line.

function [L, dc] = linelen(p1, p2)
L = sqrt(sum((p2 - p1).^2))
dc = (p2 - p1) L
endfunction

This is how we can use this function from the Scilab console prompt:

-->p1 = [0 0 0]; p2 = [3 4 5]; L1 = linelen(p1, p2)
L1  =
7.0710678
-->[L, dc] = linelen(p1, p2)
dc  =
0.4242641    0.5656854      0.7071068
L1  =
7.0710678
-->[L, dc, xyz] = linelen(p1, p2)
!--error 59
wrong number of output arguments
Arguments are:
L      dc

It is worth noting that you can call the function with either only one output argument or with two output arguments. It is an error to call the function with more than two arguments.

It is possible to invoke the function with only one input argument instead of the required two, as follows:

-->clear p1 p2
-->L1 = linelen([0 0 0], [3 4 5])
L1  =
7.0710678
-->L1 = linelen([0 0 0])
!--error 4
Undefined variable: p2

The following points are worth noting:

1. Names of input and output arguments need not be the same as those of input/output parameters.
2. The variables p1 and p2 were cleared from the Scilab workspace before invoking the function because otherwise the function would have used the value of p2 from the Scilab global workspace even though the second input argument was left out, resulting in no error.
Let us now refine this function one more step. What if the programmer wished to assume that if only one input argument were furnished when the function is invoked, the function should assume p1 = [0 0 0] and p2 to be the first and only input argument? The first requirement to achieve this goal would be for the function to determine the number of arguments (input and output) furnished during the function call. This needs to be done each time the function is invoked. This is where it becomes to have the ability to count the input and output arguments during a function call. This can be dome by using the function argn().

function [L, dc] = linelen(p1, p2)
[lhs, rhs] = argn(0)
if rhs == 1 then
p2 = p1
p1 = [0 0 0]
end

L = sqrt(sum((p2 - p1).^2))
if lhs > 1 then
dc = (p2 - p1) / L
end
endfunction

Of course, the documentation of the function must make it clear to the user what asusmptions the function is making. Note the following points:
1. The number of arguments on the left hand side of the assignments is lhs and on the right hand side is rhs, and is obtained using the function argn(0).
2. If the number of right hand side arguments is one, then the first (and only) input argument is taken to be the second point p2 and the first point p1 is assumed to be the origin.
3. If the number of output arguments is more than 1, then it is clear that the parent function expects the direction cosines dc to be computed. If the number of output arguments is less than 2, there is no need to calculate the direction cosines at all.
In fact, more complicated assumptions can be made to assume missing input arguments and only those output arguments need be calculated that are required.