There are several different types of lists in tintin which behave in a
fairly universal manner. To properly explain lists it's easiest to
explain the most basic variable type first before discussing more
complex types.
- Basic variable: The standard key = value variable.
- Simple list: A string that contains semicolon delimited fields.
{a;b;c}. Can be saved as a variable.
- Brace list: A string in which fields are delimited with braces.
{a}{b}{c}. Brace lists cannot be stored as a variable because tables
use braces as well, they must be stored as a simple list instead.
- Table: Think of this as variables nested within another variable. Or
as variables contained within another variable.
- List: A table that uses integers for its indexes. Also known as an
array. The #list command is a utility command for using tables as
arrays.
Simple Variables
Example:
#variable {simple} {Hello World!}
#show $simple
To see if the 'simple' variable exists you can use &{simple} which
will display 0 if the variable does not exist, or the variable's index
if it exists.
If you have multiple variables they are sorted alphabetically and
numerically. While it's not all that relevant for simple variables,
the first variable has index 1, the second variable index 2, and so
on.
Variable names need to start with a letter and only exist of letters,
numbers, and underscores. If you need to use a non standard variable
name this is possible using braces.
Example: #variable {:)} {Happy Happy!};#show ${:)}
Variables can be accessed using their index. While primarily useful
for tables it is possible to do this for simple variables. Use +1 for
the first variable, +2 for the second variable, etc. Use -1 for the
last variable, -2 for the second last variable, etc.
Example: #show The first variable is: *{+1} with value: ${+1}
Removing Variables
To remove a variable, use #unvariable or #unvar (every command can be
abbreviated). It's possible to remove multiple variables at once
using #unvar {var 1} {var 2} {etc}
Variables are unique to each session, so if you have multiple
sessions, removing a variable from one session won't remove it from
other sessions.
If you remove a table variable, all variables contained within that
table variable are removed as well.
Simple Lists
A simple list is a string that contains semicolon delimited fields.
Commands can be entered as simple lists, for example:
#show {a};#show {b} will execute a single line as two commands.
Several commands take a simple list as their input, these are:
#foreach, #line substitute, #path load, #list create, and #highlight.
Brace Lists
A brace list is a string in which fields are delimited with braces.
Most commands take a brace list for their arguments, for example:
#session {x} {mud.com} {1234} {mud.tin}. The session command takes
4 arguments, the 4th argument (command file) is optional.
Commands that take a simple list as their input will also accept a
brace list, keep in mind you'll have to embed the brace list in an
extra set of braces, for example: #path load {{n}{s}{w}{w}}, which is
identical to: #path load {n;s;w;w}.
Brace lists cannot be stored as variables because TinTin++ will
confuse them with tables. You can convert a brace list to a table
variable using: #list {bracelist} {create} {{a}{b}{c}} this will look
internally as: {{1}{a}{2}{b}{3}{c}}. You can then convert this table
back to a simple list using: #list {bracelist} {simplify} which will
change it to {a;b;c}.
Braces cannot easily be escaped in TinTin++. Using \{ or \} will not
work. The reason for this is due to several factors, but primarily
backward compatibility. To escape braces you must define them using
hexadecimal notation using \x7B and \x7D. See #help escape for a list
of escape options, and the help file will also remind you of how to
escape braces.
Tables
Tables are key/value pairs stored within a variable. Tables are also
known as associative arrays, dictionaries, maps, nested variables,
structures, and probably a couple of other names. There are several
ways to create and access tables.
Example: #variable {friendlist} {{bob}{bob@mail.com} {bubba}{sunset@gmail.com}}
This will create a friendlist with two entries, the key is the name of
the friend, the value is the email address of the friend. You can see
the email address of bob using: #show {$friendlist[bob]}. You can
also define this table as following:
Example:
#variable {friendlist[bob]} {bob@mail.com}
#variable {friendlist[bubba]} {sunset@gmail.com}
This would create the exact same table as the single line declaration
used previously. To see the first key in the table use:
*friendlist[+1], to see the first value in the table use:
$friendlist[+1]. To see the size of the table use &friendlist[]. To
print a bracelist of all friends use *friendlist[], to print a
bracelist of all friends whose name starts with the letter 'a' you
would use: *friendlist[a%*]. Similarly to see the number of friends
you have whose name ends with the letter 'b' you would use:
&friendlist[%*b].
See #help regexp for a brief overview of regular expression options.
While TinTin++ supports PCRE (perl-compatible regular expressions), it
embeds them within its own regular expression syntax that is simpler
and less invasive, while still allowing the full power of PCRE for
those who need it.
Example: #unvariable {friendlist[bubba]}
This would remove {bubba} from the friendlist. To remove the entire
friendlist you would use: #unvariable {friendlist}.
Example: #variable {friendlist} {{bob} {{email}{bob@ma.il} {phone}{123456789}}}
There is no limit to the number of nests, simply add more braces. To
see Bob's email in this example you would use:
#show {$friendlist[bob][email]}.
To merge two tables the #cat command can be used.
Example:
#variable {bli} {{a}{1}{b}{2}}
#variable {blo} {{c}{3}{d}{4}}
#cat {blo} {$bli}
Lists
Tables are sorted alphabetically with the exception of numbers which
are sorted numerically. If you want to determine the sorting order
yourself you can use use the #list command which helps you to use
tables as arrays.
Example: #action {%1 chats %2} {#list chats add {%0}}
Each time a chat is received it's added to the end of the 'chats' list
variable. If you type #variable chats this might look like:
#VARIABLE {chats}
{
{1} {Bubba chats Hi}
{2} {Bob chats Hi bub}
{3} {Bubba chats Bye}
{4} {Bob chats bub bye}
}
Parsing
There are various ways to parse lists and tables, using either #loop,
#foreach, #while, or #.
#loop takes two numeric arguments, incrementing or decrementing the
first number until it matches the second number. The value of the loop
counter is stored in the provided variable.
#foreach takes either a simple list or a brace list as its first
argument. Foreach will go through each item in the list and store the
value in the provided variable.
#while will perform an if check on the first argument, if the result
is true it will execute the commands in the second argument. Then it
performs an if check on the first argument again. It will continue to
repeat until the if check returns 0 or the loop is interrupted with a
control flow command. It takes special care to avoid infinite loops.
# will execute the provided argument 'number' times. For
example: #4 {#show beep! \a}
Here are some examples.
Example: #list friends create {bob;bubba;zorro}
Internally this looks like {{1}{bob}{2}{bubba}{3}{zorro}} and the
list can be parsed in various ways.
Example: #foreach {$friends[%*]} {name} {#show $name}
Example: #foreach {*friends[%*]} {i} {#show $friends[$i]}
Example: #loop {1} {&friends[]} {i} {#show $friends[+$i]}
Example: #math i 1;#while {&friends[+$i]} {#show $friends[+$i];
#math i $i + 1}
Example: #math i 1;#&friends[] {#show $friends[+$i];#math i $i + 1}
Each of the five examples above performs the same task; printing the
three names in the friends list.
If you want to get a better look at what goes on behind the scenes
while executing scripts you can use '#debug all on'. To stop seeing
debug information use '#debug all off'.
List Tables
List tables are also known as databases and the #list command has
several options to manipulate them.
For these options to work properly all tables need to have identical
keys. Here is an example list table.
#var {friendlist}
{
{1}{{name}{bob} {age}{54}}
{2}{{name}{bubba} {age}{21}}
{3}{{name}{pamela} {age}{36}}
}
To sort the list table by age you would use:
#list friendlist indexate age
#list friendlist order
To remove everyone whose name starts with a 'b' you would use:
#list friendlist indexate name
#list friendlist filter {} {b%*}
The filter option only supports regular expressions. To filter
using mathematics you would loop through the list backwards:
#loop &friendlist[] 1 index
{
#if {$friendlist[+$index][age] < 30}
{
#list friendlist delete $index
}
}
Alternatively you can use the refine option.
#list friendlist indexate age
#list friendlist refine {&0 >= 30}
To add an item to a list table there are two options:
#list friendlist add {{{name}{hobo} {age}{42}}}
#list friendlist insert -1 {{name}{hobo} {age}{42}}
Optimization
TinTin++ tables are exceptionally fast while they remain under 100
items. Once a table grows beyond 10000 items there can be performance
issues when inserting and removing items in the beginning or middle of
the table.
The plan is to eventually implement an indexable and flexible data
structure for large tables.
If you load a large table from file it's important to make sure it's
sorted, when using #write to save a table it's automatically sorted.
If you notice performance issues on large tables it's relatively easy
to create a hash table.
Example:
#alias {sethash}
{
#format hash %H %1;
#math hash1 $hash % 100;
#math hash2 $hash / 100 % 100;
#var hashtable[$hash1][$hash2][%1] %2
}
#function {gethash}
{
#format hash %H %1;
#math hash1 $hash % 100;
#math hash2 $hash / 100 % 100;
#return $hashtable[$hash1][$hash2][%1]
}
#alias {test}
{
sethash bli hey;
sethash bla hi;
sethash blo hello;
#show The value of bla is: @gethash{bla}
}
The above script will rapidly store and retrieve over 1 million items.
Looping through a hash table is relatively easy as well.
Example:
#alias {showhash}
{
#foreach {*hashtable[%*]} {hash1}
{
#foreach {*hashtable[$hash1][%*]} {hash2}
{
#echo {%-20s = %s}
{hashtable[$hash1][$hash2]}
{$hashtable[$hash1][$hash2]}
}
}
}
|