Lexicon

A Lexicon is an associative array, and is similar to the LIST type. If you are an experienced programmer who already knows what “associative array” means, you can probably skip this section and go to the next part of the page further down, otherwise read on:

In a normal array, or in kerboscript’s LIST type you specify which item in the list you want by giving its integer position in the list.

But in a Lexicon, you store pairs of keys and values, where the keys can be any type of thing you like, not just integers, and then you specify which item you want by using that key’s value.

Here’s a small example:

set arr to lexicon().
arr:add( "ABC", 1234.1 ).
arr:add( "Carmine", 4.1 ).
print arr["ABC"]. // prints 1234.1
print arr["Carmine"]. // prints 4.1

Notice how it looks a lot like a list, but the values in the index brackets are strings instead of integers. This is the most common use of a lexicon, to use strings as the key index values (and in fact why it’s called “lexicon”). However you can really use any value you feel like for the keys - strings, RGB colors, numbers, etc.

Lexicons are case-insensitive

One important difference between Lexicons in kerboscript and associative arrays in most other languages is that kerboscript Lexicons use case-insensitive keys by default (when the keys are strings). This behaviour can be changed with the :CASESENSITIVE flag described below.

Constructing a lexicon

If you wish to make your own lexicon from scratch you can do so with the LEXICON() or LEX() built-in function:

// Make an empty lexicon with zero items in it:
set mylexicon to lexicon().

If LEXICON() is given arguments then they are interpreted as alternating keys and values:

set mylexicon to lexicon("key1", "value1", "key2", "value2").

Will have the same effect as:

set mylexicon to lexicon().
mylexicon["key1"] = "value1".
mylexicon["key2"] = "value2".

Obviously when this syntax is used an even number of arguments is expected.

You can also pass any enumerable to LEXICON(). Its elements will be interpreted as alternating keys and values just like above. The following will have the same effect as the previous code fragment:

set mylist to list("key1", "value1", "key2", "value2").
set mylexicon to lexicon(mylist).

The keys and the values of a lexicon can be any type you feel like, and do not need to be of a homogeneous type.

Structure

structure Lexicon
Members
Suffix Type Description
ADD(key,value) None append an item to the lexicon
CASESENSITIVE boolean changes the behaviour of string based keys. Which are by default case insensitive. Setting this will clear the lexicon.
CASE boolean A synonym for CASESENSITIVE
CLEAR None remove all items in the lexicon
COPY Lexicon returns a (shallow) copy of the contents of the lexicon
DUMP string verbose dump of all contained elements
HASKEY(keyvalue) boolean does the lexicon have a key of the given value?
HASVALUE(value) boolean does the lexicon have a value of the given value?
KEYS List gives a flat List of the keys in the lexicon
VALUES List gives a flat List of the values in the lexicon
LENGTH scalar number of pairs in the lexicon
REMOVE(keyvalue) None removes the pair with the given key

Note

This type is serializable.

Lexicon:ADD(key, value)
Parameters:
  • key – (any type) a unique key
  • value – (any type) a value that is to be associated to the key

Adds an additional pair to the lexicon.

Lexicon:CASESENSITIVE
Type:Boolean
Access:Get or Set

The case sensitivity behaviour of the lexicon when the keys are strings. By default, all kerboscript lexicons use case-insensitive keys, at least for those keys that are string types, meaning that mylexicon[“AAA”] means the same exact thing as mylexicon[“aaa”]. If you do not want this behaviour, and instead want the key “AAA” to be different from the key “aaa”, you can set this value to true.

Be aware, however, that if you change this, it has the side effect of clearing out the entire contents of the lexicon. This is done so as to avoid any potential clashes when the rules about what constitutes a duplicate key changed after the lexicon was already populated. Therefore you should probably only set this on a brand new lexicon, right after you’ve created it, and never change it after that.

Lexicon:CASE
Type:Boolean
Access:Get or Set

Synonym for CASESENSITIVE (see above).

Lexicon:REMOVE(key)
Parameters:
  • key – the keyvalue of the pair to be removed

Remove the pair with the given key from the lexicon.

Lexicon:CLEAR()

Removes all of the pairs from the lexicon. Making it empty.

Lexicon:LENGTH
Type:scalar
Access:Get only

Returns the number of pairs in the lexicon.

Lexicon:COPY()
Return type:Lexicon
Access:Get only

Returns a new lexicon that contains the same set of pairs as this lexicon. Note that this is a “shallow” copy, meaning that if there is a value in the list that refers to, for example, another Lexicon, or a Vessel, or a Part, the new copy will still be referring to the same object as the original copy in that value.

Lexicon:HASKEY(key)
Parameters:
  • key – (any type)
Returns:

boolean

Returns true if the lexicon contains the provided key

Lexicon:HASVALUE(key)
Parameters:
  • key – (any type)
Returns:

boolean

Returns true if the lexicon contains the provided value

Lexicon:DUMP
Type:string
Access:Get only

Returns a string containing a verbose dump of the lexicon’s contents.

The difference between a DUMP and just the normal printing of a Lexicon is in whether or not it recursively shows you the contents of every complex object inside the Lexicon.

i.e:

// Just gives a shallow list:
print mylexicon.

// Walks the entire tree of contents, descending down into
// any Lists or Lexicons that are stored inside this Lexicon:
print mylexicon:dump.
Lexicon:KEYS
Type:List
Access:Get only

Returns a List of the keys stored in this lexicon.

Lexicon:VALUES
Type:List
Access:Get only

Returns a List of the values stored in this lexicon.

Access to Individual Elements

lexicon[expression]
operator: another syntax to access the element at position ‘expression’. Works for get or set. Any arbitrary complex expression may be used with this syntax, not just a number or variable name.
FOR VAR IN LEXICON:KEYS { ... }.
A type of loop in which var iterates over all the items of lexicon from item 0 to item LENGTH-1.

Implicit ADD when using index brackets with new key values

(a.k.a. The difference between GETTING and SETTING with nonexistant keys)

If you attempt to use a key that does not exist in the lexicon, to GET a value, as follows:

SET ARR TO LEXICON().
SET X TO ARR["somekey"].  // this will produce an error.

Then you will get a KOSKeyNotFoundException error, as you might expect, because the key "somekey" isn’t there in the empty lexicon you just made.

However if you use a key that does not exist yet to SET a value rather than to GET a value, you don’t get an error. Instead it actually implicitly ADDS the new value to the lexicon with that key. The example below will not give you an error:

SET ARR TO LEXICON().
SET ARR["somekey"] TO 100. // adds new value to the lexicon.

The above ends up doing the same thing as if you had done this:

SET ARR TO LEXICON().
ARR:ADD("somekey",100).

Note that while using :ADD() to make a new value in the lexicon will give you a duplicate key error if the value already does exist, using SET to create the value implicitly won’t because it simply replaces the existing value in-place rather than trying to make a new one.

This gives a duplicate key error:

SET ARR TO LEXICON().
ARR:ADD("somekey",100).
ARR:ADD("somekey",200).  // error, because "somekey" already exists.

While this does not:

SET ARR TO LEXICON().
SET ARR["somekey"] to 100.
SET ARR["somekey"] to 200. // no error, because it replaces the value 100 with a 200.

In a nutshell, using [..] to set a value in a lexicon does this: If the key already exists, replace the value with the new value. If the key does not already exist, make it exist and give it this new value.

Examples

SET BAR TO LEXICON().       // Creates a new empty lexicon in BAR variable
BAR:ADD("FIRST",10).        // Adds a new element to the lexicon with the key of "FIRST"
BAR:ADD("SECOND",20).       // Adds a new element to the lexicon with the key of "SECOND"
BAR:ADD("LAST",30).         // Adds a new element to the lexicon with the key of "LAST"

PRINT BAR["FIRST"].            // Prints 10
PRINT BAR["SECOND"].            // Prints 20
PRINT BAR["LAST"].            // Prints 30

SET FOO TO LEXICON().           // Creates a new empty lexicon in FOO variable
FOO:ADD("ALTITUDE", ALTITUDE).  // Adds current altitude number to the lexicon
FOO:ADD("ETA", ETA:APOAPSIS).   // Adds current seconds to apoapsis to the lexicon at the index "ETA"

// As a reminder, at this point your lexicon, if you did all the above
// steps in order, would look like this now:
//
//  FOO["ALTITUDE"] = 99999. // or whatever your altitude was when you added it.
//  FOO["ETA"] = 99. // or whatever your ETA:APOAPSIS was when you added it.

PRINT FOO:LENGTH.        // Prints 2
PRINT FOO:LENGTH().      // Also prints 2.  LENGTH is a method that, because it takes zero arguments, can omit the parentheses.
SET x TO "ALTITUDE". PRINT FOO[x].  // Prints the same thing as FOO["ALTITUDE"].

FOO:REMOVE("ALTITUDE").              // Removes the element at "ALTITUDE" from the lexicon.