Values
How values compare, when they count as true or false, how they turn into text, and what happens when a value is copied or shared.
Equality
eq tests equality and ne tests
inequality. (ismember uses the same rule.) The two
values must be comparable in a sensible way:
| Type | Equal when … |
|---|---|
| null | both are null |
| bool | same value |
| int | same value |
| string | same text |
| creature / object | denotes the same entity |
| prototype | same vnum |
| room | same room |
| iterable | never — not even to itself |
| block / list | same identity (the very same block or list) |
Types do not cross-compare: [eq '1' 1] is false (a string is not the
int), and [eq true 1] is false (a bool is not the int). For
case-insensitive text comparison use streqi instead of
eq.
after command (say) {
if [eq $actor $self] {
do "say talking to myself"
} else {
do "say hello [name $actor]"
}
}
[eq $actor $self] is true only when the actor and the owner are the same
creature.
Boolean contexts
A boolean context requires a value of type bool. There is no truthiness — a string, an int, a list, or null in a boolean position raises a type error and stops the script. The boolean contexts are:
ifandelifconditions;- the logic operators
and,or,not; - the handler guards
requireandunless; - the predicate a
select,every, orsomeblock returns.
So to test whether a list has elements, ask a predicate builtin —
[empty $l] or [gt [count $l] 0] — rather than handing the list itself
to if.
Conversion to text
Any value can be converted to text. This is what makes
interpolation work on any value: a $name or [cmd] piece
inside a "..." string is rendered to text and spliced in. This is the
only automatic conversion in the language — nothing else is coerced (a
string is never silently parsed as an int; use int for that).
| Type | Renders as |
|---|---|
| null | empty string |
| bool | true / false |
| int | decimal digits |
| string | itself |
| creature / object / prototype / room | an internal #kind:N# tag |
| iterable | its elements, space-joined (deferred ones render as <iterable>) |
| block | <block> |
| list | <list> (its elements are not rendered) |
In text displayed to a player, you will want to interpolate the
descriptive text — [name $actor], [level $actor] — rather than
rendering an entity reference directly:
after command (say) {
do "say [name $actor] is level [level $actor]"
}
This says, e.g., "Puff is level 26."
But, in text meant to be resolved by a command, you will want to interpolate the entity reference:
after command (say) {
do ">$actor That's exactly what I mean!"
}
This will tell the saying creature "That's exactly what I mean!", but it will tell that exact creature even if another creature shares its name. In the same vein, object references only refer to a specific object.
Binding and sharing
When a value is read from a variable or passed as an argument, whether the new binding is independent depends on the type:
- Scalars and entity references are independent. Changing one variable never affects another that held the same value. (An entity reference in two variables still points at the one game entity — the entity is not duplicated.)
- Iterables traverse independently. Advancing one binding does not move another (see Iterables).
- Blocks and lists are shared by identity. Two bindings of the same block or list are the same object: they compare equal by identity, and a block keeps access to the variables of the scope it was defined in (see Scope).
See also
- Types — the value kinds themselves.
- Operators —
eq,ne,and,or,not. - Strings and interpolation · Variables · Scope