Control structures - if, try, for, while, until¶
Control structures control the flow of execution by providing mechanism for branching and repeating execution of code. Imba has several different control structures.
if
blocks control branchingtry
blocks handle exceptions- loops (
for
,while
,until
) allow repetitive execution of code blocks
Cheats¶
- Imba has the
if
,try
,while
,until
andfor
blocks. - All blocks are expressions which can be assigned and passed around.
- There are no parentheses around conditions.
- There is no punctuation in blocks (e.g.,
if x
). if
block can haveelse if
andelse
branches.for
,white
,until
can be passed and assigned as arrays.for
,white
,until
canbreak
andcontinue
.for x in arr
orfor x, idx in arr
to loop over arrays.for key of obj
orfor key, val of obj
to loop over object properties.- There is no
for i; i < j; i++
version offor
loop in Imba. catch
is optional intry
block.
The if
block¶
Sometimes we want to do different things depending on some condition. For instance, 'if user is logged in, show them the profile page, and otherwise take them to the log in page.'
Just like the name suggests, the if
blocks are only evaluated if some
condition is met. The condition can be any valid Imba expression, including any
of the control blocks found in this section (yes, if
block itself, too!).
For example:
1 2 3 4 | var lives = 0 if lives is 0 'You are dead' |
We can also specify what happens in the other case:
1 2 3 4 5 6 7 | var lives = 3 if lives is 0 'You are dead' else lives -= 1 "You have {lives} more lives" |
The if
block is not restricted to just if
and else
branches. One or
more additional conditions can be specified as else if
branches. For
example:
1 2 3 4 5 6 7 8 9 10 | var lives = 3 if lives is 0 'You are dead' else if lives is 1 lives -= 1 'You are mine next time!' else lives -= 1 "You have {lives} more lives". |
If blocks can be assigned to variables.
1 2 3 4 5 6 7 8 9 10 | var lives = 3 var x = if lives is 0 'You are dead' else lives -= 1 "You have {lives} more lives" x # "You have 2 more lives" |
Ternary expression¶
In some cases, we can write the if
block as a ternary expression to save
space. Ternary expression is not technically a control structure, but we will
mention it here because we don't have a better things to do anyway.
1 2 | var lives = 3 var isDead = if lives is 0 then yes else no |
The else if
branches cannot be used in ternary expressions.
The try
block¶
Perfectly valid code will sometimes throw exceptions. Exceptions are objects generated by some error condition or thrown by some code. Exception objects will propagate through the application from the point where it was thrown, then back up through the path that lead to the point. If it is not caught somewhere on the path, it will eventually reach the JavaScript engine itself, and be treated as an 'uncaught' exception. (This is usually going to show up as a traceback in the developer console or in the terminal.)
1 2 3 4 5 6 7 | def foogGun throw Error 'bug!' try footGun catch e console.log "That was close! Let's do it again!" |
The e
variable in the catch
branch is the error object that was thrown by
the footGun
method.
Note that the catch
branch is optional. If we simply wish to suppress an
exception without doing anything, we can completely omit it.
1 2 3 | try fooGun # Look, mom, no catch! |
Like if
blocks, the try
block can be assigned
1 2 3 4 | var afermath = try footGun catch e 'Feeling exceptionally good!' |
The while
loop¶
The while
loop is the simplest control structure for repeating blocks of
code. It repeats the block while some condition is met, hence the name.
1 2 3 4 | var bullets = 1000 white bullets > 0 bullets-- |
Other than letting the while loop run until the condition no longer applies,
we can also end it prematurely by using the break
or return
statements.
1 2 3 4 5 6 7 8 | var count = 0 while yes # yes is always yes, so this will loop indefinitely count++ break count # 1 |
The return
statement can only be used inside methods or do blocks as it
doesn't really terminate the while loop, but returns from the method or do
block completely.
While looping inside a while
loop, we can use continue
to skip the rest
of the block. It's basically like jumping back to the top of the block.
1 2 3 4 5 6 7 | var evenNumbers = [] var i = 0 while i++ < 200 if i % 2 continue evenNumbers.push i |
The until
loop¶
The until
loop is similar to the while
loop, with a reverse condition: it
will stop only once the condition is met. It is just a shorter way to say
while not condition
.
1 2 3 4 | var baloons = [1, 2, 3, 4, 5] until baloons:length is 0 baloons.pop |
We can use break
, return
and continue
inside until
just like in the
while
loops.
The for
loop¶
Whereas the while
and until
loops are more generic, for
loop is used
specifically for iterating over array members and object properties.
There are two variants of for
loops:
for ... in
for arrays, strings, and array-like objects.for ... of
for object properties.
The for ... in
loop is used like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var colorIndex = { R: '#ff0000' G: '#00ff00' B: '#0000ff' C: '#00ffff' M: '#ff00ff' Y: '#ffff00' } var colorSequence = ['R', 'M', 'R', 'G', 'B', 'C', 'M'] var colors = [] for colorKey in colorSequence colors.push colorIndex[colorKey] |
For loops are actually arrays, and they can be assigned and passed. In the
previous example we kept pushing into the colors
array. This can be written
simply like so:
1 2 | var colors = for colorKey in colorSequence colorIndex[colorKey] |
In for
loops, we can also access the the indices of members we are iterating
over.
1 2 3 | var colors = for colorKey, index in colorSequence intensity: (index + 1) * 100 color: colorIndex[colorKey] |
The for ... of
loop is used for objects. In it's simpler form, for ... of
iterates over the keys.
1 2 3 4 5 6 7 8 9 10 11 | var colorIndex = { R: '#ff0000' G: '#00ff00' B: '#0000ff' C: '#00ffff' M: '#ff00ff' Y: '#ffff00' } var allColors = for key of colorIndex key |
We can also use for ... of
to iterate over both keys and values.
1 2 3 4 | var reverseIndex = {} for key, val of colorIndex reverseIndex[val] = key |
Just like the while
loop, we can use break
, return
and continue
to
terminate the loop or skip iterations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var players = [ {name: 'OP', dmg: 400, hp: 100} {name: 'Nuclear', dmg: 300, hp: 200} {name: 'Voe', dmg: 280, hp: 210} {name: 'Polygon', dmg: 220, hp: 180} {name: 'Glitter', dmg: 440, hp: 120} {name: 'Vanilla J', dmg: 300, hp: 50} ] var strongPlayers = for player in players if player:dmg >= 300 player:name else continue strongPlayers # ['OP', 'Nuclear', 'Glitter', 'Vanilla J'] |