Part 9
Functions

Subjects covered...

	LEN, STR$, VAL, SGN, ABS, INT, SQR
	DEF FN

Consider the sausage machine. You put a lump of meat in at one end,
turn a handle and out comes a sausage at the other end. A lump of pork
gives a pork sausage, a lump of fish gives a fish sausage, and a lump
of beef gives a beef sausage.

Functions are practically indistinguishable from sausage machines but
there is a difference; they work on numbers and strings instead of
meat. You supply one value (called the argument), mince it up by doing
some calculations on it, and eventually get another value - the
result.

	Meat in        ->    Sausage Machine    ->    Sausage out

	Argument in    ->    Function           ->    Result out

Different arguments give different results, and if the argument is
completely inappropriate the function will stop and give an error
report.

Just as you can have different machines to make different products -
one for sausages, another for combs, a third for dish cloths, and so
on, different functions will do different calculations. Each will have
its own name to distinguish it from the others.

You use a function in expressions by typing its name followed by the
argument, and when the expression is evaluated the result of the
function will be worked out.

As an example, there is a function called LEN, which works out the
length of a string. Its argument is the string whose length you wish
to find, and its result is the length, so that if you type...

	PRINT LEN "Jammy Smears"

...the +3 will write the answer 12, i.e. the number of characters
(including spaces) in the string 'Jammy Smears'.

If you mix functions and operations in a single expression, then the
functions will be worked out before the operations. Again, however,
you can circumvent this rule by using brackets. For instance, here are
two expressions which differ only in the brackets, and yet
calculations are performed in an entirely different order in each case
(although, as it happens, the end results are the same).

	LEN "Fred" + LEN "Bloggs"
	4+LEN "Bloggs"
	4+6
	10

...and...

	LEN ("Fred" + "Bloggs")
	LEN ("FredBloggs")
	LEN "FredBloggs"
	10

Here are some more functions...

STR$ converts numbers into strings: its argument is a number, and its
result is the string that would appear on the screen if the number
were displayed by a PRINT statement. Note how its name ends in a '$'
sign to show that its result is a string. For example, you could
say...

	LET a$= STR$ 1e2

...which would have exactly the same effect as typing...

	LET a$="100"

Or you could say...

	PRINT LEN STR$ 100.0000

...and get the answer 3, because STR$ 100.0000 is equal to "100", the
length of which is 3 characters.

VAL is like STR$ in reverse - it converts strings into numbers. For
instance...

	VAL "3.5"

...is equal to the number 3.5.

VAL is the reverse of STR$ because if you take any number, apply STR$
to it, and then apply VAL to it, you get back the number you first
thought of.

However, if you take a string, apply VAL to it, and then apply STR$ to
it, you do not always get back to your original string.

VAL is an extremely powerful function, because the string which is
its argument is not restricted to looking like a plain number - it can
be any numeric expression. Thus, for instance...

	VAL "2*3"

...is equal to 6. Even...

	VAL ("2"+"*3")

...is equal to 6. There are two processes at work here. In the first,
the argument of VAL is evaluated as a string - the string expression
"2"+"*3" is evaluated to give the string "2*3". Then, the string has
its double quotes stripped off, and what is left is evaluated as a
number: so '2*3' is evaluated to give the number 6.

There is another function, rather similar to VAL, though probably less
useful, called VAL$. Its argument is still a string, but its result is
also a string. To see how this works, recall how VAL goes in two
steps: first its argument is evaluated as a string, then the string
quotes stripped off this, and whatever is left is evaluated as a
number. With VAL$, the first step is the same, but after the string
quotes have been stripped off in the second step, whatever is left is
evaluated as another string. Thus...

	VAL$ """Ursula""" is equal to 'Ursula'

(Notice how the string quotes proliferate again.) Try...

	LET a$="99"

...and print all of the following: 'VAL a$', 'VAL "a$"', 'VAL
"""a$"""', 'VAL$ a$', 'VAL$ "a$"' and 'VAL$ """a$"""'. Some of these
will work, and some of them won't - try to explain all the answers.

SGN is the sign function (sometimes called signum). It is the first
function you have seen that has nothing to do with strings, because
both its argument and its result are numbers. The result is +1 if the
argument is positive, 0 if the argument is zero, and -1 if the
argument is negative.

ABS is another function whose argument and result are both numbers. It
convert the argument into a positive number (which is the result) by
forgetting the sign, so that for instance...

	ABS -3.2

...is equal to...

	ABS 3.2

...which is simply equal to 3.2.

INT stands for integer part - an integer is a whole number, possibly
negative. This function converts a fractional number into an integer
by 'throwing away' the fractional part, so that for instance...

	INT 3.9

...is equal to 3.

Be careful when you are applying it to negative numbers, because it
always rounds down. Thus for instance...

	INT -3.1

...is equal to -4.

SQR calculates the square root of a number, i.e. the result that,
when multiplied by itself, gives the argument, for instance...

	SQR 4

...is equal to 2 because 2 x 2 is equal to 4.

	SQR 0.25

...is equal to 0.5 because 0.5 x 0.5 is equal to 0.25.

	SQR 2

...is equal to 1.4142316 (approx) because 1.4142316 x 1.4142316 is
equal to 2 (almost).

If you multiply any number (even a negative number) by itself, the
answer is always positive. This means that negative numbers do not
have square roots, so if you apply SQR to a negative argument you get
the error report 'A Invalid Argument'.

You can also define functions of your own. Possible names for these
are FN followed by a letter (if the result is a number) or FN followed
by a letter followed by '$' (if the result is a string). These
function are much stricter about brackets - the argument *must* be
enclosed in brackets.

You define a function by putting a DEF statement somewhere in the
program. For instance, here is the definition of a function 'FN s'
whose result is the square of the argument...

	10 DEF FN s(x)=x*x: REM the square of x

The 's' following the DEF FN is the name of the function. The 'x' in
brackets is a name by which you wish to refer to the argument of the
function. You can use any single letter you like for this (or, if the
argument is a string, a single letter followed by '$').

After the '=' sign comes the actual definition of the function. This
can be any expression, and it can also refer to the argument using the
name you've given it (in this case, 'x') as though it were an ordinary
variable.

When you have entered this line, you can invoke the function just like
one of the +3's own functions, by typing its name, 'FN s', followed by
the argument. Remember that when you have defined a function yourself,
the argument must be enclosed in brackets. Try it out a few times...

	PRINT FN s(2)
	PRINT FN s(3+4)
	PRINT 1+ INT FN s ( LEN "chicken"/2+3)

Once you have put the corresponding DEF statement into the program,
you can use your own functions in expressions just as freely as you
can use the computer's.

INT always rounds down. To round to the nearest integer, add 0.5 first
- you could write your own function to do this...

	20 DEF FN r(x)= INT (x+0.5): REM gives x rounded to the
	   nearest integer.

You will then get, for instance...

	FN r(2.9)	is equal to 3
	FN r(2.4)	is equal to 2
	FN r(-2.9)	is equal to -3
	FN r(-2.4)	is equal to -2

Compare these with the answers you will get when you use INT instead
of 'FN r'. Type in and run the following...

	10 LET x=0: LET y=0: LET a=10
	20 DEF FN p(x,y)=a+x*y
	30 DEF FN q()=a+x*y
	40 PRINT FN p(2,3), FN q()

There are a lot of subtle points in the program. Firstly, a function
is not restricted to just one argument: it can have more, or even none
at all - but you must still always keep the brackets.

Secondly, it doesn't matter whereabouts in the program you put the DEF
statements. After the +3 has executed line 10, it simply skips over
lines 20 and 30 to get to line 40. They do, however, have to be
somewhere in the program - they can't be in a command.

Thirdly, 'x' and 'y' are both the names of variables in the program as
a whole, and the names of arguments for the function 'FN p'. 'FN p'
temporarily forgets about the variables called 'x' and 'y', but since
it has no argument called 'a', it still remembers the variable 'a'.
Thus when 'FN p(2,3)' is being evaluated, 'a' has the value 10 because
it is the variable, 'x' has the value 2 because it is the first
argument, and 'y' has the value 3 because it is the second argument.
The result is then, '10+2*3' which is equal to 16. When 'FN q()' is
being evaluated, on the other hand, there are no arguments, so 'a',
'x' and 'y' all still refer to the variables and so have the values
10, 0 and 0 respectively. The answer in this case is '10+0+0' which is
equal to 10.

Now change line 20 to...

	20 DEF FN p(x,y)= FN q()

This time, 'FN p(2,3)' will have the value 10 because 'FN q' will
still go back to the variables 'x' and 'y' rather than using the
arguments of 'FN p'.

Some BASICs (not +3 BASIC) have functions called LEFT$, RIGHT$, MID$
and TL$.

LEFT$(a$,n) gives the substring of a$ consisting of the first n
characters.

RIGHT$(a$,n) gives the substring of a$ consisting of the characters
from nth on. [This is wrong. RIGHT$(a$,n) gives the substring of a$
consisting of the n characters at the end at a$ - RIGHT$("wibble",4)
would give "bble".]

MID$(a$,n1,n2) gives the substring of a$ consisting of n2 characters,
starting at the n1-th.

TL$(a$) gives the substring of a$ consisting of all its characters
except the first. [This was in the ZX80's BASIC.]

You can write some user-defined functions to do the same...

	10 DEF FN t$(a$)=a$(2 TO ): REM TL$
	20 DEF FN l$(a$,n)=a$( TO n): REM LEFT$

Check that these work with strings of length 0 or 1. Note that our 'FN
l$' has two arguments, one a number and the other a string. A function
can have up to 26 numeric arguments (why 26?) and at the same time up
to 26 string arguments.


Exercise...

Use the function 'FN s(x)=x*x' to test SQR. You should find that...

	FN s( SQR x)

...equals 'x' if you substitute any positive number for 'x', and...

	SQR FN s(x)

...equals 'ABS x' whether 'x' is positive or negative. (Why is the ABS
there?)
[Back] [Contents] [Next]