Range Over Iterators in Modelica

Let’s look at the List type from the previous example again. In that example, we had an AllElements method that returned a slice of all elements in the list. With Modelica iterators, we can do it better - as shown below.

model List
  parameter Real head;
  parameter Real tail;
end List;

model element
  parameter Real next;
  parameter Real val;
end element;

function Push
  input List lst;
  input Real v;
algorithm 
  if lst.tail == 0 then
    lst.head := element(val=v);
    lst.tail := lst.head;
  else
    lst.tail.next := element(val=v);
    lst.tail := lst.tail.next;
  end if;
end Push;

function All
  input List lst;
algorithm 
  real seq[1+size(list)];
  integer i;
  for i in 1:size(list) loop
    seq[i] := lst.head;
    yield(seq[i]);
    lst.head := lst.head.next;
    i := i + 1;
  end for;
  return seq;
end All;

function genFib
    output Real fib[10];
protected 
    Integer a = 1;
    Integer b = 1;
algorithm
    for i in 1:10 loop
        if not yield(a) then
            return;
        end if;
        Integer temp = a + b;
        a := b;
        b := temp;
    end for;
end genFib;

model Main
  List lst;
algorithm
  Push(lst, 10);
  Push(lst, 13);
  Push(lst, 23);

  for e in All(lst) loop
    Modelica.Utilities.Streams.print(string("Element: ") + String(e));
  end for;

  Real all[:];
  all := All(lst);
  Modelica.Utilities.Streams.print("all: " + Modelica.Utilities.Strings.join(all, " "));

  for n in genFib() loop
    if n >= 10 then
        break;
    end if;
    Modelica.Utilities.Streams.print(string("Fib: ") + String(n));
  end for;
end Main;

To run this program, compile and simulate it using your Modelica-compliant environment.

$ omc Main.mo
$ omc Main.mos
$ omedit

The output will look something like this:

10
13
23
all: 10 13 23
1
1
2
3
5
8

Now that we can run and build basic Modelica programs, let’s learn more about the language.