We make software for humans. Custom Mac, Windows, iOS and Android solutions in HyperCard, MetaCard, and RunRev LiveCode
by Jacqueline Landman Gay
HyperActive Software
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.
Functions are distinguished syntactically in two ways; a function is called using either the keyword the
or it is called using parentheses. You are probably using functions all the time in LiveCode and may not even know it. LiveCode has hundreds of built-in functions; for example, the date
is a function (using the keyword the
,) which can also be written date()
using the parentheses form. When you use the date
or date()
, LiveCode does an evaluation and sends back today's current date. This process happens invisibly inside the LiveCode engine, which contacts the OS, gets the system date, and returns it to your script. Then your script can use the date information to do some work.
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:
which can also be written:the number of cards
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:number(cards)
In this case, "theNumCds" contains a number, which is equal to the number of cards in the stack.put number(cards) into theNumCds
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:
The parametersfunction addNumbers num1,num2 put num1 + num2 into theTotal return theTotal end addNumbers
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:
This handler will send 16 and 4 to our custom functionon 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
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:addNumbers(theFirstNumber,theSecondNumber)
because there is no place to put the date that is returned. You must provide a place:the date
or:put the date into myDate
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 the date into field "today"
put addNumbers(theFirstNumber,theSecondNumber) into myTotal
Here is another example. This one removes all vowels from a word and returns only the consonants:
In this example, the word "chimpanzee" is sent to the functionon 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
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.
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
:
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 areaon addNumbers num1,num2 put num1 + num2 into theTotal return theTotal end addNumbers
the result
. The calling handler can retrieve the information at will by asking for the result
:
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.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
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.