Iterables
An iterable is an on-demand sequence — the language's one way to talk about a collection of things. There are no arrays of creatures or objects; instead, builtins hand you iterables and you walk them.
An iterable is anything you can walk: a list, or any
iterable. A bare string is not iterable — to iterate its
words, convert it first with words.
Producers and consumers
A producer gives you an iterable. The collection builtins are
producers: creatures / people,
objects, inventory,
equipment, fighting,
words, list, and the filtering
select / slice.
A consumer reads an iterable. Some take a block and run it
per element — each, select,
every, some. Others read it directly —
count, first, nth,
empty, ismember, choose.
after command (say) {
each [creatures $self] { <c>
do "smile $c"
}
}
creatures produces an iterable over the creatures in the
room; each consumes it, running the block once per creature.
Lazy sequences
Iterables can be produced on demand: an element may be computed
only when a consumer asks for it. The filtering producers
select and slice are especially lazy —
they yield each element as it is pulled, never computing the whole
result up front. That means [first [select … ]] does only as much
work as it takes to find the first match.
after command (say) {
let nums [list 1 2 3 4 5]
let evens [select $nums { <n> [eq [% $n 2] 0] }]
do "say first even is [first $evens]"
}
select builds a deferred iterable of the even numbers;
first pulls just enough to report 2.
Iterables are never equal
Two iterables never compare equal with eq — not even an
iterable to itself. To compare contents, walk them. To test membership,
use ismember.
Strings are not iterable
A string is a single value, not a sequence. Walking its words takes an explicit conversion:
each [words "north east south west"] { <dir>
do "say I could go $dir."
}
Without words, handing the bare string to each is a
run-time type error.