## Chapter 17 - User Defined Functions: FN

You will be pleased to know that all the information about PROCs covered in the previous section also applies to user defined functions - FN. The only difference is that FNs return a value to the calling line, hence, like the inbuilt functions such as SQR, they can be used in expressions.
 REM Squaring a number using FN A=4 B=FN_Square(A) PRINT A;" squared is ";B END DEF FN_Square(Num) =Num^2
We'll look at the definition first. As can be seen, we tell BASIC that we're declaring a function by using FN instead of PROC. There's no ENDFN. The end of the function is indicated by the line starting with '='. The expression is calculated and this value is returned to the caller, line 3 in our case.

In some other dialects of BASIC, you have to include the return type in the function's name, like when you declare a variable. BBC BASIC allows you to do this, but it doesn't check the return type against the type specified in name. Usually, you don't bother.

Like PROCs, FNs can be as long and complex as you choose to make them. They can call other PROCs and FNs. The one rule I do suggest you stick to, with both types of routine, is only have one exit point. Having multiple = lines, depending on conditions might seem like a good idea, but does lead to trouble. It is much cleaner to use a local variable to hold the result and then return this at the end:

 REM Vowel test INPUT "Enter a letter: " Char\$ IF FN_IsAVowel(Char\$) THEN PRINT Char\$;" is a vowel" ELSE PRINT Char\$;" is not a vowel" ENDIF END DEF FN_IsAVowel(Ch\$) LOCAL Result% IF INSTR("AEIOUaeiou", LEFT\$(Ch\$,1)) THEN Result%=TRUE ELSE Result%=FALSE ENDIF =Result%
Rather than this, where if more code is added each return point can get lost in the rest of the code:
 REM ... DEF FN_IsAVowel(Ch\$) IF INSTR("AEIOUaeiou", LEFT\$(Ch\$,1)) THEN =TRUE ELSE =FALSE ENDIF
You can only pass single values back, not arrays or structures. (There is a method of doing this, but that definitely falls into the domain of advanced.) If you need to pass a value back, it's better to pass the whole thing as a parameter and manipulate it in the function.

 Tip:  Find that routine In any but the most trivial program you will have several PROCs and FNs. To locate the definition of the routine you are trying to find, right click anywhere in the editor and as if by magic, all the PROCs and FNs contained in the currently open program are listed at the bottom of the popup menu. To jump to one, point and click.

 Tip:  Routines with the same name It should be pretty obvious that you don't have two PROCs or FNs with the same name, however BB4W won't object if you do. If BASIC finds two routines with the same name, it will use the last one and ignore all others. With a little program, that's easy to spot. When the programs grow to more than one page, it becomes difficult to detect and if you are using libraries, which allow you to split your code over several files, a major headache. If the code you're editing doesn't seem to be having any effect, look for duplicate names.

That's all there is. As stated, all the things about LOCAL, PRIVATE, variable scope etc. are just the same as with PROCs.

Exercise

1) It's a very useful function that waits for the user to press y (yes) or n (no) in response to a prompt and returns either TRUE or FALSE. It should, of course, check for case.
2) Write a function FN_Lower that accepts a string. It goes through each character in the string and converts all uppercase letters to lowercase. Other characters are left as they are. Return the converted string.