Maps in Modelica

Here is the translated content in Markdown format suitable for Hugo with the Go code example translated to Modelica:

Maps are Modelica’s built-in associative data type (sometimes called hashes or dicts in other languages).

model ExampleMaps
  outer function Environment_initialize;
end ExampleMaps;

To create an empty map, use the builtin DynamicArray and Tuple:

model ExampleMaps
  import SI = UnitConversions.ConversionFunctions.SIunits;
  package key = SI.String;
  import ExpPackage = SI.Real;
  Real exp;
  SI.Tuple(key key, exp exp);
  SI.DynamicArray(SI.Tuple) m;
end ExampleMaps;

Set key-value pairs using typical name[key] = val syntax:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
end ExampleMaps;

Printing a map will show all of its key/value pairs:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  for i in 1:size(m.lst, 1) loop
    SI.Print(m.lst[i]);
  end for;
end ExampleMaps;

Get a value for a key with name[key]:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  Real v1 = SI.GetValueForKey(m, "k1");
  SI.Print(v1);
end ExampleMaps;

If the key doesn’t exist, the zero value of the value type is returned:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  Real v3 = SI.GetValueForKey(m, "k3");
  SI.Print(v3);
end ExampleMaps;

The builtin size returns the number of key/value pairs when called on a map:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  Integer len = size(m.lst, 1);
  SI.Print(len);
end ExampleMaps;

The builtin delete removes key/value pairs from a map:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  SI.DeleteMapEntry(m, "k2");
  for i in 1:size(m.lst, 1) loop
    SI.Print(m.lst[i]);
  end for;
end ExampleMaps;

To remove all key/value pairs from a map, use the clear builtin:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  SI.ClearMap(m);
  for i in 1:size(m.lst, 1) loop
    SI.Print(m.lst[i]);
  end for;
end ExampleMaps;

The optional second return value when getting a value from a map indicates if the key was present in the map. This can be used to disambiguate between missing keys and keys with zero values like 0 or "". Here we didn’t need the value itself, so we ignored it with the blank identifier _:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) m(lst=[
    SI.Tuple(key="k1", exp=7), 
    SI.Tuple(key="k2", exp=13)
  ]);
  Boolean prs;
  SI.Tuple result, prs;
  (result, prs) = SI.GetMapEntry(m, "k2");
  SI.Print(prs);
end ExampleMaps;

You can also declare and initialize a new map in the same line with this syntax:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) n(lst=[
    SI.Tuple(key="foo", exp=1),
    SI.Tuple(key="bar", exp=2)
  ]);
  for i in 1:size(n.lst, 1) loop
    SI.Print(n.lst[i]);
  end for;
end ExampleMaps;

The maps package contains a number of useful utility functions for maps:

model ExampleMaps
  SI.DynamicArray(SI.Tuple) n(lst=[
    SI.Tuple(key="foo", exp=1),
    SI.Tuple(key="bar", exp=2)
  ]);
  SI.DynamicArray(SI.Tuple) n2(lst=[
    SI.Tuple(key="foo", exp=1),
    SI.Tuple(key="bar", exp=2)
  ]);
  if SI.MapsEqual(n, n2) then
    SI.Print("n == n2");
  end if;
end ExampleMaps;

Note that maps appear in the form map[k:v k:v] when printed with SI.Print.

map: map[k1:7 k2:13]
v1: 7
v3: 0
len: 2
map: map[k1:7]
map: map[]
prs: false
map: map[bar:2 foo:1]
n == n2

Next example: Functions.