Scoping-out Variables and Functions

Let's quickly go over the kinds of primitive objects that we use while building bots on the Palace. If you were writing official docs, you might call this list "Iptscrae data types."

We can store values like "Istanbul" or arrays like [ "Constantinople" "New Amsterdam" ] in variables using the = sign.
We can name and store atom lists, to be used as as functions, using DEF. We can "run" such an atomlist at at time by passig it to the iptscrae command EXEC.
Here are a couple of examples.

; variable creation and assignment using =
1 TRUE =
"wiggly" worldType =
[ "Scooby" "Scrappy" ] dogDoos =

; declaring an atom list function with DEF
} select_say DEF

Note that the select_say function itself contains multiple atom lists IFELSE takes both "yes" and "no" atomlists as arguments. Many iptscrae commands take atomlists and sublists, particularly EXEC, ALARMEXEC, IF, WHILE, DEF, and all of the various ON SIGNON, ON MACRO3, ON OUTCHAT, etc "event handlers."
To use select_say we can replace
select_say EXEC
(don't forget the EXEC!!!) the result will act just like SAY in most cases, but is also smart enough to know when you really wanted to *whisper* because you had someone clicked.


Iptscrae doesn't distinguish between functions, subroutines, procedures, procs, applets and such thingies... they're all just "atom lists." If an atom list is named and stored away using DEF, you can call it a function or proc or whatever.
For clarity, I try to always give variables multi-word names like worldType or longVariableName, and functions names_like_this that is, underscore_separators. Finally, for the rare value that's defined as an unchanging constant, I usually use ALLCAPS in the computer brain, what's TRUE tends to stay that way.
In programmer-speak, all of these names are typically known as identifiers.
Iptscrae itself actually ignores identifiers' case, so don't make the mistake of thinking that, say, "msx" "msX" and "MSX" are different names.


When an identifier is declared within the bubble of an { atom list } its definition is restricted to that atom list, and the subsequent sublists contained in the same atom list. Outside the scope of its enclosing bubble, it doesn't exist!
In other words, it you use a variable called creamCheese in your INCHAT handler, don't expect to be able to get that creamCheese back in the OUTCHAT. They're living in two separate universes. You can have two separate creamCheese variables, one for each of the handlers, and neither will ever smear the other.
Unless, that is, they are both declared as GLOBAL variables.
If an identifier is declared as GLOBAL before it's used, its value(s) will be stored in a special shared portion of the Palace's memory. Any other atom list that likewise refers to the GLOBAL identifier (by using a GLOBAL command of its own) can subsequently read and use it just like a "local" identifier. The GLOBAL command gives us a way to share values and functions between all the parts of our bot script.

A Global Caveat
As of this writing, GLOBAL doesn't work with arrays. Simple-value variables, yes. Atom lists, yes. Arrays, no. Go figure.
The way to get around this problem is to assign arrays into a string, the later extract it using STRTOATOM:

    [ 1 2 3 42 911 ] theArray =
    ; putting array values into a string
    0 i =
	theArray i GET ITOA & " " &
	i ++
    } { i theArray LENGTH < } WHILE
    theString =

    ; extracting array values from a string
    "\x5b " theString & " \x5d newArray =" & STRTOATOM EXEC    

Hex values shown here are for the characters "[" and "]"

When to Use GLOBAL

If an atom list is contianed within another atom list, it will inherit the definitions of the enclosing list. You don't have to be redeclaring lots of GLOBAL vars every time you use IF or WHILE as long as you do make the appropriate declarations in the surrounding code. My personal habit is to pile-up the GLOBAL declarations at the beginning of each event handler.
There are several kinds of { atom lists } that don't have any enclosing scope at the time they execute, and so they must always include GLOBAL declarations for every shared variable and function that they might use.

Event Handlers
These are the big blocks like ON SIGNON and ON OUTCHAT.
Functions Launched by EXEC
Once they start executing, they "pop" up to the top of the scope chain. They can still get values passed on the stack (like select_say above), but shared values should be declared as GLOBAL within the EXEC'd atomlist.
Functions Launched (and Delayed) by ALARMEXEC
These are even more restrictive than EXEC functions, because they can't know what the stack will be like by the like they actually get around to executing. ALARMEXEC is the most isolated case everything must be either declared GLOBAL or completely self-contained within the atom list. As an alternative to using global data, you could try a stringy workaround.
Trickier still, you need to remember that the global values that an ALARMEXEC atom list might access will be accessed then, at the time of the alarm not at the time you schedule via ALARMEXEC!!!
Command-line Iptscrae
You can execute Iptscrae commands directly from your text box, by escaping the text with a leading / slash mark. Since the stack state can't be known in advance, this is roughly as isolated as ALARMEXEC and needs GLOBAL declarations for anything you want to use from your Cyborg.ipt.

Global Persistence

When a variable or function is declared GLOBAL, its name and value persists between events. Not just between different OUTCHATs and alarm events, but between rooms and even between palaces (when connected via NETGOTO in scripts like "warp" or through a palace jumpstation like "the slabs"). Once declared, the only way to effectively wipe out a global value is to shut down your entire palace session, via the "Disconnect" menu. Not attractive, but that's life.
A few clever folks have turned this potential problem into a useful tool for example, the now-common ICameFrom global macro can let any palace script know about the recent history of users, who may have come there via link from another palace.