Skip to main content
Version: 23.3

Messages

SenseTalk is an object-oriented language that works by passing messages from one object to another. When a message is sent to an object, it can respond if its script has a handler for that message. If the object does not have a handler for a particular message, that message is passed along to some other object. For more information on working with handlers, see Handlers.

Objects do things only when they receive a message. An object can send messages to itself, or they may be sent to it by another object, or by the environment in which the script resides. For example, when a script is invoked from the command line, it is sent a message based on the name of the script, which causes the script to run.

To begin with, all you need to know is that when a message is sent to an object, it can either receive and handle that message, or it can ignore it. Continue reading to look at messages and how they are sent.

Sending Messages

When a script is running, it sends messages constantly as it executes its commands. A message is always a single word, and the simplest message-sending statement is a single-word command, which is the name of the message to be sent. For example, the second line of this script sends the message “greetTheUser”:

put "Hello, World!"
greetTheUser
put farewellMessage()

In this script, the put commands on the first and third lines also send messages. In fact, with the exception of a few fundamental SenseTalk control structures, almost every command in a script sends a message. Function calls, such as the call to the “farewellMessage()” function above, also send messages.

Command Messages and Function Messages

SenseTalk actually sends two different types of messages. Command messages are sent by commands, such as greetTheUser in the example above. Function messages are sent by function calls, such as farewellMessage() in the example above. The two message types are identical except for the type of handler that will receive them (see Handlers). For more information on how to call functions, see Functions. For more information on how to use commands, see Commands and Comments.

Where are Messages Sent?

We said earlier that messages are used to allow objects to communicate with one another, so you might be wondering where the “greetTheUser” and “put” messages above are being sent. What object will receive these messages? The answer is very simple, though perhaps somewhat surprising: the object containing these commands will send these messages to itself!

While at first it may not appear to be terribly useful for an object to send messages to itself, in practice any message which is not handled by the object is passed along for possible handling by other objects or ultimately by one of SenseTalk’s built-in commands or functions.

Messages can also be sent directly to some other particular object, if desired. This is done using the tell command, send command, run command, run function, the square-bracket messaging syntax, or by using of, . or 's like this:

put the salary of writer into authorPay -- sends "salary" to writer
get investor's balance("Checking") -- sends "balance" to investor
add paycheck.netIncome() to it -- sends "netIncome" message to paycheck

The Message Path

When a message is sent to an object, the message follows a path through several different objects. Each object along the path which the message follows will be given a chance to handle the message. If the object has a handler for that message, the instructions in that handler are carried out. Otherwise, the message is offered to each of the other objects along the path in turn, until one is found which handles the message.

Usually, once a message is handled by an object, that is the end of it. However, in some cases an object’s handler might choose to pass the message on along the path, allowing other objects the opportunity to handle that same message (see the pass commands under Passing Messages).

BackScripts and FrontScripts

Looking at the larger picture, in addition to the object to which the message is sent (known as the target object), the message path might also include other objects, both before and after the target object and its helpers. These inclusions are made up of the objects in the the FrontScripts and the BackScripts, plus any additional objects that might be included by the host application.

The BackScripts is a global property containing a list of objects that get the chance to handle a message after the target object, if the target object did not handle it. So, by inserting an object (a library or script) into the BackScripts that object’s handlers become available to be used by any script, while still allowing any individual scripts to provide their own handlers to override the BackScripts behavior. The BackScripts is such a useful mechanism that two special commands, Start Using and Stop Using, are provided to simplify adding and removing objects in the BackScripts.

The FrontScripts is a rarely-used global property containing a list of objects that get the chance to handle a message before the target object is even offered the message. This gives these objects the chance to intercept a message and potentially override behaviors of any object, which is rarely wanted but occasionally useful for tasks such as logging a message before passing it along the message path.

Start Using Command

Behavior: Inserts a script or other object into the BackScripts. This is equivalent to the insert <object> into the BackScripts command but is simpler and more readable.

Syntax:
start using object
insert object into back
insert object into the BackScripts

Example:

start using "Folder1/Helper1" // Puts Helper1 (from Folder1) into the BackScripts

Related:

Stop Using Command

Behavior: Removes a library or script previously inserted into the BackScripts. This is equivalent to the remove <object> from the BackScripts command but is simpler and more readable.

Syntax:
stop using object
remove object from back

Example:

stop using "Folder1/Helper1" // Removes Helper1 (of Folder1) from the BackScripts

Related:

Helpers

When a message is passed to each object along the path, that object’s script is checked to see if it contains a handler for the message. If so, that handler is executed. If not, the message is also passed to each of the object’s helpers in turn, to see if any of them have a handler for the message. When checking whether one of the helpers has an appropriate handler, its list of helpers is also consulted, as well as their helpers (if any) and so forth. Only when all of the helpers have been checked will the message be passed to the next object along the message path.

Objects in the BackScripts list only receive messages not handled by any other objects in the message path. They are commonly used to provide basic functionality that might be needed by many different objects. Objects in the FrontScripts list get the chance to intercept and handle any message before it reaches the target object. This capability is rarely used, but might be powerful in certain situations.

Host Application

After all the objects in the message passing path (and their helpers) have had a chance to handle it, a message will be delivered to the host application and SenseTalk itself. If the message corresponds to a built-in command or function, that command or function will be processed. Some messages are recognized by SenseTalk but ignored. If the message is neither recognized and handled by SenseTalk nor recognized and ignored, the host application looks for a script file with the same name as the message. Typically, it at least looks in the same folder where the calling script is located, and possibly looks in other folders as well. If a script file cannot be found to handle the message, an error is raised.

The Full Message Passing Path

When a message is sent to an object (known as the target object), the full path of the message includes the following objects, in this order:

  • Objects in the FrontScripts in the order in which they were inserted (with the object most recently inserted in front receiving the message last) and their helpers
  • The target object and its helpers
  • Objects in the BackScripts (with the object most recently inserted in back receiving the message last) and their helpers
  • The host application and SenseTalk itself
  • Other script files in folders identified by the host application

At each step along the way, if a handler for the message is found, that handler is run. If such a handler does not pass the message on, it is considered handled and goes no further. However, a handler might also choose to pass the message along using the pass command (or one of its variants). If it does, the message continues along the message passing path as though it had not been handled, and later objects in the path will have a chance to receive that message.

The Target

Because a message might be handled by any of several different objects along the message path, those objects might need to find out the object to which the message was sent. This is the purpose of the target, which identifies the target object. For example, an object inserted into the BackScripts might have an incrementAccessCount handler that increments a counter each time it is run, like this:

on incrementAccessCount
add 1 to the accessCount of the target
end incrementAccessCount

Here, rather than maintaining a single counter in its own accessCount property, it is updating the accessCount property of whatever object received the incrementAccessCount message.

Passing Messages

A handler can choose not to handle a message it has received, or can perform some actions and then pass the message on to other scripts later in the message passing path, using a pass command. For more information on working with handlers, see Handlers.

Pass Command

Behavior: Passes the current message along to the next object in the message passing path. This terminates execution of the current handler. If handlerOrFunctionName is given rather than the generic term message, the name supplied must be the same as the name of the current handler.

Syntax:
pass handlerOrFunctionName
pass {the} message

Example:

pass message

Pass ... and Continue Command

Behavior: Passes the current message along to the next object in the message passing path, just as the pass command does, but allows the current handler to continue running after the message has been handled elsewhere. The current handler resumes executing after the message is handled by some other object later in the message passing path. Any value returned by the other object is available in the result immediately after the pass ... and continue command. After executing a pass ... and continue command, any later attempt to pass that message (using any of the pass commands) will be unable to actually pass the message along, as no message is ever delivered to the same object twice.

Syntax:
pass handlerOrFunctionName and continue
pass {the} message and continue

Example:

pass message and continue

Pass ... Without Helping Command

Behavior: Passes the message along to the next object following the object being helped in the message passing path. This differs from the pass command when used in a helper. In essence, the helper is saying "I'm not able to help with this message." The helpers' helpers are not given a chance to handle the message, but the message is passed to later helpers of the object being helped, and to other objects later in the message passing path. The current handler stops running when this command is executed.

Syntax:
pass handlerOrFunctionName without helping
pass {the} message without helping

Example:

pass message without helping

Pass Original Message To ... Command

Behavior: Use pass original message to ... to pass the current message directly to some other object. This differs from other forms of the pass command, which pass the current message along to the next object in the message passing path.

This form of the pass command is intended for use within undeliveredMessage handlers to try passing the original (undelivered) message to some other object for handling. If that object handles the message, that will be the end of it, and execution of the current handler will end. If the other object does not handle the message, execution will continue in the current handler. In this way an undeliveredMessage handler can attempt to deliver the original message to one or more other objects which may be able to handle it. See Undelivered Messages to learn more. If and continue is specified, the current handler resumes executing after the message is passed, whether or not it was handled by the other object.

Syntax:
pass original message to object {and continue}

Example:

pass original message to alterEgo

Message Information

CallStack Function

Behavior: The callStack function returns a list of SenseTalk Frame objects providing information about the current execution frames. Call callStack() to obtain information about how the current handler was called.

Syntax:
the callStack
callStack()

Example:

put property "Line" of the last item of the callStack into currentLine

MessageType Function

Behavior: Returns a value indicating the type of message being handled, such as “Command” or “Function”. This can be used to enable a generic (“to handle”) handler to take different actions depending on how it was called. Other possible values that may be returned include “GetProp” and “SetProp”.

Syntax:
the messageType
messageType()

Example:

if the messageType is "Function" then return theAnswer

Parameters and Results

Passing Parameters

To learn how to pass parameters, see the Parameters and Results page.

Information Returned by a Message

Function messages, and sometimes command messages, return a value. The value returned by a function message becomes the value of the function call expression. So, in the example below, the value returned by the roundToNearest function message is the value that is put into the monthlyPayTothePenny variable:

put "roundToNearest(salary/12, 0.01)" into monthlyPayTothePenny

The value returned can be a single value, or may in some cases be a list or property list containing multiple values.

The Result

When a value is returned from a command message, it is available on the following line as the result. Because the value of the result is reset to empty for each statement, a given result can only be accessed on the very next statement. For more information on the result, see the Result Function.