Dictionaries

A dictionary is flexible data structure. Dictionaries:

  • May optionally have an assigned text value.
  • Hold a flexible set of key-value pairs. Keys are text names.
  • Information is automatically sorted by key, resulting in fast searching and retrieval.
  • Key-value pairs can be added and removed efficiently and without limit.
  • Values may be other dictionaries, allowing you to create complex data structures.

Create a Dictionary Using the Dictionary() Function

In this example ServerLocations is a dictionary of server names and where each is located.

ServerLocations = Dictionary();
ServerLocations["Primary"] = "Cleveland";
ServerLocations["Backup1"] = "Orlando";

 

In the following example, DriverServers is a dictionary of dictionaries, each holding the names of primary and packup servers.

DriverServers = Dictionary();
DriverServers["Modicon1"] = Dictionary();
DriverServers["Modicon1"]["Primary"] = "ServerX";
DriverServers["Modicon1"]["Backup"]  = "ServerY";
 
DriverServers["Modicon2"] = Dictionary();
DriverServers["Modicon2"]["Primary"] = "ServerY";
DriverServers["Modicon2"]["Backup"]  = "ServerX";

Within a dictionary, all keys must always be unique by definition. Attempting to create a duplicate key by assigning a new value to a key with a non-unique name will simply result in the original key being assigned the new data value. Dictionaries may be defined such that their keys are case sensitive (in which case "a" will come after "Z") or they may be non case sensitive. Unless otherwise specified, they will not be case sensitive.

Create a Value with Attached MetaData

This discussion of MetaData is included for the sake of completeness while discussing dictionaries. For any reason that you would use MetaData, a structure can be used instead and will use less memory than variables with MetaData.

The function, MetaData, provides a means of attaching extended information to the value in a variable. Note that the extended information is attached to the value, not to the variable.

As an example, one might use this to attach a timestamp to a value. While metadata is implemented using a dictionary, these are separate tools with separate uses. The concept is inspired by XML. If used with a parameter that is not a dictionary, the result is to attach metadata to that object thereby turning it into a dictionary. If the value is copied to another variable, the metadata goes with it.

MetaData(Dictionary,  Key);

Example:

MetaData(X, "Width", 1) = 5;

X becomes a non-case sensitive dictionary, having no root value and possessing one key named "Width" that has the associated value, 5.

More commonly, you would use this to attach extended information to an existing variable as shown in the following example:

Y  =  10;
MetaData(Y,  "Area")  =  20;

In this example, Y starts as an integer and then becomes a non-case sensitive dictionary having a root value of 10 (the original value) and possessing one key named "Area" which initially has a value of 20.

You can even use this technique to turn an array into a dictionary - something that could not be done using the Dictionary() function.

Z = New(5, 10);  
MetaData(Z,  "Rate", 0) = 42.7;

Z becomes a case sensitive dictionary having a root value that is the array [5, 10]  and possessing one key named "Rate" that has a value of 42.7.

You can turn a dictionary into a value with metadata by assigning a root value via the RootValue() function. This is an uncommon practice and should be avoided except for the niche use case of building nested dictionaries.

Practice with dictionaries

Arrays are useful for storing data in a clearly enumerated order, 0, 1, 2... But often, data is associated with keys that aren't in a tidy order. There are cases where driver error codes provide an excellent example of this.

In this example, you will use an array and listbox to simulate random error codes coming from hardware. A dictionary stores the key-value pairs of defined error codes and matching messages.

Create a new script application and copy the following to the Graphics submodule.

Graphics
[
  ErrCodes                      { a dictionary of error codes          };
  SimErrors                     { array simulating errors received     };
  Choice                        { selection from simulated error array };
  Index                         { offset into array                    };
  Msg                           { message to display                   };
]

Init [ 
  If 1 Main;
  [
    ErrCodes = Dictionary(1);
    ErrCodes[0x2]  = "No connection";
    ErrCodes[0x4]  = "Missing adapter";
    ErrCodes[0x10] = "Error retrieving value";
    ErrCodes[0x30] = "Command not found";
    ErrCodes[0x92] = "Invalid syntax";
    
    SimErrors = New(5);
    SimErrors[0] = 0x2;
    SimErrors[1] = 0x4;
    SimErrors[2] = 0x10;
    SimErrors[3] = 0x30;
    SimErrors[4] = 0x92;    
  ]
]

Main [
  System.DropList(40, 60, 140, 40 { Boundaries of list }, 
                 SimErrors { Data displayed }, 
                 "" { No title }, 
                 Index { Highlighted index }, 
                 1, 1 { Focus ID, trigger }, 
                 FALSE { Editable field }, 
                 Invalid { Starting value }, 
                 Choice { Variable to set }, 
                 FALSE { No bevel }, 
                 0 { Align top of list }); 
   Msg = Concat("Error code: ", Choice, " ... Message: ", ErrCodes[Choice]);
   ZText(150, 60, Msg, 12, 0);
]
{ End of System\Graphics }
>