What is a Function?
LiveCode's programming language is intuitive and easy to learn. It is very much like spoken English in some ways, and many commands can be written exactly as you would say them in natural language syntax. However, it is also a full and expansive programming language in its own right, and as such, it supports all the contructs that are found in any programming language. This includes two basic types of programming routines: command handlers and function handlers. Function handlers are usually referred to simply as "functions".
Many LiveCode newcomers are not sure what the differences are between function handlers and command handlers. This document explains how functions work, and what the basic difference is between a handler that acts as a function and one that acts as a command.For a more advanced discussion on how useful functions can be, see Geoff Canyon's excellent article.
What is a function?
Some functions need to know a bit of information before they can work; for example, the LiveCode function the number (also written number().) You need to pass a parameter to the function - some extra information - that tells it what you want to count, whether it is buttons, or cards, or graphics, or anything else. If we want to know the number of cards, we pass "cards" to the function this way:
the number of cards
which can also be written:
LiveCode then goes through the stack and adds all the cards to get a total, which is sent back to your script. Your script receives that value and needs to store it into a variable so that it can use it later:
put number(cards) into theNumCds
In this case, "theNumCds" contains a number, which is equal to the number of cards in the stack.Writing your own functions
If LiveCode does not have a built-in function to do something you want, you can write your own function to do it instead. If your script uses a function you write yourself, the calling handler cannot use the when using it; the handler must use the parentheses form. Thus, a custom function called myFunction cannot be called with the myFunction - you must use myFunction() instead.
A note about the message path: The message path for functions is identical to the message path for command handlers. You should place your function at the level where any handler that calls it can use it. For example, if your custom function is used only by a single button, then an appropriate place for that function would be in the button script. If many buttons use the function, then it could go in the card script, a group script, or the stack script.
Suppose we want to add two numbers together and get a total. (This is a very simple task, but it makes a good example.) We can write a function called "addNumbers" like this:
function addNumbers num1,num2 put num1 + num2 into theTotal return theTotal end addNumbers
The parameters num1 and num2 are like baskets that hold whatever values the original handler sends. In this case, they will each contain a number. The special word return tells LiveCode to send the variable theTotal back to the handler that asked for the information. Note that whenever LiveCode sees the return keyword, the function will exit immediately afterward. This means that return is usually - but not always - the last line in the function's script.
So, this function takes two numbers that are passed to it in the parameters, adds them together, and sends back a total. Now we can write a handler that uses the function:
on myHandler put field "firstNum" into theFirstNumber -- say the field \ contains 16 put field "secondNum" into theSecondNumber -- say this one \ is 4 put addNumbers(theFirstNumber,theSecondNumber) into field \ "sumTotal" end myHandler
This handler will send 16 and 4 to our custom function addNumbers. The addNumbers function will catch these two numbers in its parameters num1 and num2, add them together, and send back 20. The handler myHandler will receive that 20 and put it into the field "sumTotal". The field now displays 20.
When you use a function in a handler, you must provide a place for its results to go - a variable usually, or sometimes a field. For example, this will not work:
because there is no place for the returned information to be stored. A handler that uses a function must provide a place to put the information that the function sends back. This is true of built-in LiveCode functions too. For example, this will not work:
because there is no place to put the date that is returned. You must provide a place:
put the date into myDate
put the date into field "today"
A handler that uses a custom function must follow the same rule. It must provide a place for the returned information to be stored:
put addNumbers(theFirstNumber,theSecondNumber) into myTotal
Here is another example. This one removes all vowels from a word and returns only the consonants:
on myHandler put getConsonants("chimpanzee") into field 1 end myHandler function getConsonants theWord put "aeiou" into theVowels repeat for each char i in theWord if i is not in theVowels then put i after theChars end repeat return theChars end getConsonants
In this example, the word "chimpanzee" is sent to the function getConsonants, where it is placed automatically into the parameter theWord. The function checks each character in the word and if it is not a vowel, it puts the character after a list called theChars. When it is finished checking each character, it returns the list of characters, which automatically gets sent back to the calling handler myHandler. The characters sent back in this example would be "chmpnz", so that is what field 1 will display.
Functions can be as short or as long as you want, and sometimes can be very complicated. But the basics are always the same: a handler asks a function to do some work and often sends some parameters to the function to tell it what to work with. The function does the work and returns the finished calculation to the original handler. The handler can use the finished calculation any way it wants, just as if it were any other variable.
What's the difference between a function and a command handler?
Not very much, when you get right down to it. They are both just a list of commands that accomplish something. The primary difference is that there is a built-in way for a handler to use the results of a function.
However, command handlers can also return results, in exactly the same way as functions do. The difference is in how the calling handler receives the result. When using a function, the result is sent back automatically and all the calling handler has to do is provide a storage place for it. When using a command handler, the calling handler must instead ask for the result specifically. We could change the addNumbers() function into a command handler by simply replacing the keyword function with the keyword on:
on addNumbers num1,num2 put num1 + num2 into theTotal return theTotal end addNumbers
Now that it is a command handler, the total that has been calculated is not sent back to the calling handler automatically. Instead, the calculation is placed in the system-wide storage area the result. The calling handler can retrieve the information at will by asking for the result:
on myHandler put 16 into theFirstNumber put 4 into theSecondNumber addNumbers theFirstNumber,theSecondNumber get the result -- this asks for the total put it into field "sumTotal" end myHandler
Most of the time it is easier to just write the calculation as a function and allow LiveCode to send the result back automatically. However, the above is valid and in some situations may be preferable, though this author cannot think of any good examples of when this would be required.
Note that the result changes its value frequently and without warning, since a good many LiveCode commands use it to store temporary data - for example, the "ask" and "answer" dialogs use the result to store the name of the button the user clicks. If you will be retrieving the result from a command handler, it is a good idea to do so as soon after issuing the command as possible. If you allow too many lines of script to go by before retrieving the result, you may find that another command has changed its contents and the result no longer contains what you think it does.