Collections by Dannii Willis


This extension provides support for array and map data structures. Unlike normal Inform lists, arrays can contain multiple different kinds. Maps are key-values pairs, where both keys and values can be (almost) any kind.

Chapter - Collection references

The basic data structure in this extension is the collection reference. A collection reference can be of any sayable kind. You can make a collection reference with these phrases:

collection value (sayable value)
collection value (name of sayable kind)

The second will make a collection reference of that kind with its default value.

You can test whether a collection reference is of a particular kind, whether it is equal to another collection reference, and say the name of kind of the collection reference with these phrase:

if kind of (collection reference) is (name of kind)
if (collection reference) equals (collection reference)
say "[kind of collection reference]"

Unfortunately the names of numerical kinds cannot all be determined. If you have a weight kind, then this last phrase will display "0kg".

You can read the value of a collection reference with this phrase:

(collection reference) as a (name of kind)

If you try to read it with the wrong kind then an error will be shown.

You can update the value of a collection reference with these phrases; again the kind must be the same.

set (collection reference) to (value)
(collection reference) = (value)

If you read a text collection reference into an existing text variable, then the two texts will become disconnected; changing the text variable will not result in the collection reference's internal text being changed. You can however set the collection reference to the text variable. Or if you read the collection reference into a new variable ("let T be mycolref as a text") then the internal text will be exposed as the new variable, so that changes to the variable will result in the internal text being changed.

Chapter - Arrays

You can create an array and then access its internal list with these phrases:

new/empty array
let (new name) be (collection reference) as a list

You can then use the normal Inform list manipulation phrases. Note that you can only add collection references to the internal list, so you will have to manually wrap your values using "collection value (value)", and if you want to remove anything from the list, you need to manually destroy it first.

Chapter - Maps

There is no Inform data structure that fits a map, but you can use these phrases to create and access them:

new/empty map
if (R - collection reference) has key (K - value):
set key (K - value) of (R - collection reference) to (V - value)
get key (K - value) of (R - collection reference)
delete key (K - value) of (R - collection reference)

When setting a key or value, you do not need to pass in a collection reference, the extension will handle wrapping the key/value in a reference for you. On the other hand, if you do set a key or value to an existing collection reference, it will be used directly and will become owned by the map, so that you don't need to destroy it individually. Unlike for individual collection references, if you are setting a value in a map for a key that already exists, the kind of the new value does not have to be the same as the kind of the old value.

If you would like a slightly more programmy way of accessing maps, you can use these phrases:

(R - collection reference) => (key - value) = (V - value)
(R - collection reference) => (key - value)

You can also repeat through the keys of a map with this phrase:

repeat with (loopvar - nonexisting collection reference variable) of/in (collection reference) keys

Chapter - Cleaning up

Collection references exist outside the normal Inform model, so you must manually destroy them in order to not leak memory. Destroying an array or map will clean up all of its contents as well.

destroy (collection reference)

Example: * Collections demo

"Collections demo"

Include Collections by Dannii Willis.

The Lab is a room.
In the lab is a coin.

When play begins:
     let mymap be a new map;
     set key "location" of mymap to the Lab;
     set key "time" of mymap to 12:17 PM;
     mymap => "player" = player;
     let myarray be a new array;
     let myarray internal be myarray as a list;
     add collection value true to myarray internal;
     add collection value false to myarray internal;
     mymap => "truth states" = myarray;
     mymap => coin = "coin";
     say "[mymap][paragraph break]";
     repeat with key in mymap keys:
         let V be mymap => key;
         say "Key: [key] ([kind of key]), value: [V] ([kind of V])[line break]";
     destroy mymap;