Variables

A variable is a named box holding one value. You read a variable with the $ sigil — $actor, $count — and you create or change one with let, set, or const.

A variable can hold a value of any type, and a single variable may hold different types at different times. Variables are not the same as persistent entity state: state that must survive between handler runs lives in slots reached through store/recall, not in variables.

Reading a variable — $name

$name (or the braced form ${name}) evaluates to the value of the nearest enclosing binding of that name (see Scope for what "nearest enclosing" means).

$actor          # the creature that triggered the handler
$self           # the script's owner
${count}        # braced form, same meaning as $count

The braced form is handy inside a string when text follows the name: "${count}coins" reads count, while "$countcoins" would look for a variable named countcoins.

A $name that has no binding anywhere is caught when the script is compiled — it never loads. (A handler-injected name the event does not provide, like $actor in a tick handler, is a run-time error instead.)

Introducing a local variable — let

let name value creates a fresh, mutable local variable in the current scope. The name is written without $ — the sigil appears only when reading.

let counter 0
let target $actor

let shadows any outer binding of the same name. Declaring a name that is already bound in the same scope is a compile-time error.

Changing a local variable — set

set name value rewrites an existing binding, searching outward through the enclosing scopes. It never creates a binding.

let counter 0
set counter [+ $counter 1]      # mutates the let above

set of a name that is not bound, or of an immutable const, is a compile-time error. Because set searches outward, a block can change a variable owned by an enclosing scope — the basis of the counter idiom in Scope.

An immutable local — const

const name value introduces an immutable local: it can be read but never set. Use it for fixed values you want to name.

const GREETING 'gossip'
do "say $GREETING"

(const is also a top-level declaration form; see Scope.)

Local variables are fresh every time

A handler's local variables start fresh on each invocation and are gone when it ends. They do not carry over from one event to the next. To keep state between invocations, write it to persistent entity state with store/recall.

Examples

after command (say) {
  let counter 0
  set counter [+ $counter 1]
  do "say counter is $counter"
}

Introduces counter, mutates it, then reports its value ("counter is 1").

const GREETING 'gossip'

after command (say) {
  store $self 'state' $GREETING
  do "say my state is [recall $self 'state']"
}

Names a constant, then uses it as a persistent value the script can read back later. The mob would report "my state is gossip."

See also