Tables

Tables are one of the most useful types available to users of the NeXtMidas shell and macro language. A table is a collection of values each with a unique tag (or name).

Syntax

When defined on the command line or in a macro, a table is specified in the following format:

nM> res t:mytable {TAG1=VAL1,TAG2=VAL2,...,TAGn=VALn}
Where the table is defined within a pair of braces ({...}) and each element of the table is specified by a TAG=VALUE syntax with a comma (,) separating subsequent elements.

Valid Tag Names

All tags in a table must be one or more characters in length and may contain only numbers, upper-case letters and the underscore. This is basically the same as identifiers in C/C++ except that it may begin with a number and is case-insensitive. Tags may be specified on the command line or in a macro with lower-case letters since they will be automatically converted to upper case by the NeXtMidas shell.

Regular Expression for Tag Names: [0-9A-Z_]+

There is no upper limit to the length of a tag name but users are likely to find that tag names longer than 16 characters are unwieldy to use.

Note:
Older versions of NeXtMidas allowed tag names to contain dashes (-). This behavior has been deprecated since it caused confusion as to whether a statement like ^MYTBL.FOO-9 represented a single table reference (^{MYTBL.FOO-9}) or a table reference followed by a subtraction (^{MYTBL.FOO}-9).

Types in a Table

When a table is specified on the command line, its type is automatically assigned by the NeXtMidas shell. For example:

nM> res t:mytable {ONE=1.0,TWO=2.0,TEN=10.0}
Would create a table with three doubles in it. It is possible to specify the type of the value by giving the appropriate type specifier before the tag name (see Typecasting in a Macro for the list of valid type specifiers). For example:
nM> res t:mytable {B:ONE=1.0,B:TWO=2.0,F:TEN=10.0}
Would create a table with two bytes and a float.

Inside a table, strings should be quoted, numbers should not be quoted, and subtables should be within a pair of braces. For example:

nM> res t:mytable {NUMBER=1,STRING="My String",SUBTABLE={ONE=1,TWO=2}}
One exception is that single-word strings with no special characters will be accepted even if they are not quoted (though this practice is discouraged).

Since NeXtMidas 2.9.0, Tables can be specified on the command line with values that are\ Strings that contain escape sequences. These escape sequences are translated when the Table is constructed. The escapes are the standard Java escapes (a backslash ("\") followed by a special character (e.f. "\n" for newline) or the Unicode escape sequence, which is "\u" followed by four hex digits (e.g. "\u00b1" for the plus-minus sign).

    Example (Your browser font may not be able to display the smiley face correctly):
      nM> res t:mytable {A="\u263a"}   ! A smiley face
      nM> res mytable
      T: MYTABLE         = Table of 1 entries
      1S:  A              = ☺
      

Translation

When translating a table reference, translation always goes to the end unless the translation is done using the caret-brace (^{...}) syntax. Here are a few examples:

 1: nM> res mytable {A=1,B=2,C=3,D={A=10,B=20,C=30},X=9,Y=99,Z=999}
 2: nM> res a d
 3: nM> res b {a="a",b="b",c="c",D={A="x",B="y",C="z",D="z"}}
 4: nM> res mytable.d.a 
      L: MYTABLE.D.A     = 10
 5: nM> res mytable.^a.a  
      ERROR: ...
 6: nM> res mytable.^{a}.a
      L: MYTABLE.D.A     = 10
 7: nM> res mytable.^{b.a}.d
      D: MYTABLE.A.D     = 1.0
 8: nM> res mytable.^{b.^a.d}
      ERROR: ...
 9: nM> res mytable.^{b.^{a}.d}
      L: MYTABLE.Z       = 999
10: nM> res mytable2 {A=1,B=2}{C=3}{D=4,E=5,A=999}
11: nM> res mytable2
      T: MYTABLE2        = Table of 5 entries
      L:  A              = 999
      L:  B              = 2
      L:  C              = 3
      L:  D              = 4
      L:  E              = 5
      
Line 5 causes an error because it tried to access mytable.^{a.a} but a is a string with the value "d", not a table. Similarly line 8 attempts to access a.d. To avoid situations such as this, the caret-brace syntax is always recommended when dealing with translation in the middle of a table name.

Line 10 shows an example of the automatic table merging function. When the parser sees a "}{" in a table definition it treats it like a comma. This allows the macro writer to append qualifiers onto a file name (e.g. "^{filename}{FS=1K}") that may or may not include qualifiers to begin with. Note that if there are any duplicate entries (such as "A=1" and "A=999" on Line 10) only the last one will be kept.

While the above examples may seem a bit contrived, many applications use the values within one table as the keys used to access another table. It is not uncommon to see the nesting of these two or three levels deep.

Altering a Table

Once a table has been defined the values in the table can be easily modified or new values added using the RESULT or SET commands. For example:

nM> res mytable.a 7.0 
This will set the value A in my table to be the double value 7.0. To set it to a byte use the following:
nM> res b:mytable.a 7.0 

Note that before adding values to a subtable the subtable must first be inserted:

nM> res mytable {ONE=1,TWO=2}
nM> res mytable.SUBTABLE.a 3
  ERROR: Table Entry SUBTABLE not found for put of A
nM> res mytable.SUBTABLE { }
nM> res mytable.SUBTABLE.a 3
nM> res mytable.SUBTABLE.a
  L: MYTABLE.SUBTABLE.A = 3
      

Values in a table can be removed using the REMOVE command. For example:

nM> rem mytable.a 
This will remove A from MYTABLE.

Sorting a Table

A table can be set to use one of three internal modes:
Mode Underlying Storage Mechanism Nominal Order of Operation Sortable
Get Add Remove
KV(1) NeXtMidas KeyVector O(n) O(1) O(n) YES
HT Java Hashtable O(1) O(1) O(1) NO
FB(2) Byte Buffer n/a n/a n/a n/a
(1) KV is the default mode.
(2) FB mode is used only for serialization of the table. A table in FB mode will automatically switch to KV mode on first use.

The tradeoff between KV mode and HT mode is sortability versus access time. The TABLE command provides functions that can change the mode of a table and sort a table.

Table ONLY Data Types

Special Table only data types have been added for serialization and deserialization of Time objects and Java Number subclasses.

The serialization of Time objects as T: Table entries is enabled by setting the Table flag SerializeTimeAsTColon.

The serialization of Java Numbers using lower case types can be enabled either by CoreIO.IOOptions.FavorJavaBehaviorOverTraditionalMidasBehavior or by the Table flag KeepJavaNumericType.

 1: nM> table javatab LOAD nxm.sys.test.test_table_java_numbers.tbl &
           /flag=+KeepJavaNumericType
 2: nM> res javatab /all
 3: nM> res mytable2
      T: JAVATAB         = Table of 6 entries
      x:  JAVALONG       = 123456789
      b:  JAVABYTE       = 127
      f:  JAVAFLOAT      = 1.23
      l:  JAVAINTEGER    = 12345678
      d:  JAVADOUBLE     = 1.23456789
      i:  JAVASHORT      = 1234

 4: nM> res timetab {MYTIME=T:2019:06:12::9:08:56.123456789012}
 5: nM> res timetab /all
      T: TIMETAB         = Table of 1 entries
      O:  MYTIME         = 2019:06:12::09:08:56.123
 6: nM> invoke ,, timetab.mytime.toString(12)
      Invoke: ANSWER = 2019:06:12::09:08:56.123456789012