When should I use semicolons (;) and when shouldn’t I in mobl?

It’s a common question. Here’s the reasoning behind requiring semicolons in one context and none in the other.

In mobl, semicolons signify imperative execution, i.e. execution from top to bottom. For instance:

var n = 8;
n = n + 10;
n = n * n;

First create a variable n, and assign 8 to it, then add 10 to n, then multiply n with itself and save the result to n, and then show a pop-up dialog with the result.

A lot of mobl is not imperative but declarative, i.e. you don’t define a recipe of how to get from A to B, but instead you define the desired end-result and let mobl figure out how to realize it. An example of this is mobl’s user interface language:

screen root() {
  group {
    list(t in Task.all()) {
      item { checkBox(t.done, label=t.name) }

Ostensibly you may think these are basically just a list of imperative statements. First render a header, then a group, then loop over each item in Task.all(). However, you shouldn’t think of it this way. While this may be the execution order in an initial render, parts of the user interface may react to application state changes later, e.g. when new tasks are added to the Task.all() collection. As a result, the user interface may change a lot after the initial render. In a user interface you define what you want, not how to realize this vision, unlike script where you spell out the steps to a desired result.

To make this conceptual difference clear in the syntax, mobl uses semicolons. Imperative code in mobl uses semicolons, declarative code does not.