Statements
Overview
Fantom code is written as a series of statements just like Java or C#. However unlike Java/C#, Fantom statements are not required to be terminated with a semicolon. A Fantom statement may be terminated one of three ways:
- newline
- semicolon
- end of block
}curly brace
By convention a simple newline is the preferred mechanism for separating statements. A semicolon is only used when placing multiple statements on the same line. For example these are all valid Fantom statements:
if (authenticated)
{
sendToHomePage
return true
}
if (authenticated)
{
sendToHomePage();
return true;
}
if (authenticated) { sendToHomePage; return true }
The first version is the preferred syntax. The third version also exhibits good mojo if it is compact enough to keep the code readable.
The Fantom grammar is not perfectly unambiguous when you omit semicolons. So on occasion you will run into a situation when the compiler complains and you might need to stick in a semicolon - but in practice this rarely happens. Another side effect of this is that Fantom requires the opening parenthesis of a method call to be on the same line as the method identifier:
// ok
call(...)
// not ok
call
(...)
This rule also applies to the opening square bracket of an index operation:
// ok
list[...]
// not ok
list
[...]
Expression Statements
The most common type of statement is a stand alone expression. The following expressions are considered valid statements:
- Any assignment expression including the increment/decrement operators
- Method calls (or chains of method calls)
Return Statement
The return statement is used to exit a method:
// if Void method:
return
return <expr>
// if non-Void method:
return <expr>
If the enclosing method is Void, then return simply returns control
back to the code which called the method. A return statement in a Void
method may optionally include a expression which is run before return.
The expression returned by a Void method may evaluate to any type including
Void.
If the enclosing method is non-void, then the return statement includes
the expression used to return a result object to the caller.
If returning an expression, then the expression must start on the same
line as the return keyword:
// this is ok
return call(x,
y, z)
// this is illegal
return
call(x, y, z)
Fantom allows you omit the return keyword if your method or closure
contains exactly one statement:
Str name() { return "Bob" } // long version
Str name() { "Bob" } // short version
Convention is to omit the return keyword for single statement returns.
Local Variables
Local variables may be declared using the following syntax:
// syntax
<type> <identifier> := <init>
// example
Str name := "Jack Shephard"
Fantom supports type inference
for local variables, which allows you to omit the type signature.
If the type signature is omitted, then the variable is typed according
to the initializer expression. In the example above the right hand
side resolves to a Str, so we could rewrite the statement above as:
name := "Jack Shephard"
Fantom convention encourages use of type inference when possible. However
if the right hand side expression resolves to an ambiguous type, then
you will need to specify the variable's type signature. The most common
case when type inference doesn't work is when you need to initialize a
local variable to null.
Fantom uses the := operator for local variable initialization rather than
the standard = assignment operator. The primary purpose of the :=
syntax is to distinguish normal assignments from local declarations.
This syntax captures programmer intent better and enables the compiler
to catch typos like a misspelled local.
Fantom does not support the comma operator to declare multiple local variables like Java or C#. In practice though most locals will be declared using type inference.
If a local variable is not explicitly assigned an initial value, then
it implicitly defaults to null, false, 0, or 0.0f following
same rules for field defaults. This is a little different than Java
or C# which require definite assignment.
If Statements
Fantom supports if and else using the Java/C# syntax:
if (<cond>)
<block>
if (<cond>)
<block>
else
<block>
if (<cond>)
<block>
else if (<cond>)
<block>
else
<block>
The if condition must evaluate to a sys::Bool expression.
The block can be a single statement or a block of multiple statements
delineated by { } curly braces.
Loop Statement
Fantom supports while and for loops using familiar Java and C#
syntax. Although you'll find when writing Fantom that most looping
is actually done using closures.
While Statement
Fantom supports while loops using Java/C# syntax:
// syntax
while (<cond>)
<block>
// example
while (p != null)
p = p.next
The while loop executes its block until its condition
evaluations to false. The while condition must evaluate to
a sys::Bool expression. The block can be a single statement or
a block of multiple statements delineated by { } curly braces.
Fantom doesn't currently support do while loops.
For Statement
Fantom supports for loops using Java/C# syntax:
// syntax
for (<init>; <cond>; <update>)
<block>
// example
for (i:=0; i<10; ++i)
echo(i)
The for condition must evaluate to a sys::Bool expression. The
block can be a single statement or a block of multiple statements
delineated by { } curly braces. All three expressions of the
for loop are optional. If the cond expression is omitted, it defaults
to true. The init expression is executed once on loop entry and the
update expression after each run of the loop. The for loop runs
until the condition evaluates to false.
Like Java/C# the init expression of the for loop can be a local
variable declaration which defines a local scoped only within
the for loop. Unlike Java/C# the comma operator is not supported
in the init and update expressions.
Break Statement
The break statement is used with both the for and while loops
to break out of the loop. For example:
for (i:=0; i<10; ++i)
{
if (i == 3) break
echo(i)
}
echo("done")
// prints
0
1
2
done
The break statement always applies to the inner-most loop.
Fantom does not support labeled breaks.
Continue Statement
The continue statement is used with both the for and while
loops to jump back to the top of the loop. For example:
for (i:=0; i<4; ++i)
{
if (i == 2) continue
echo(i)
}
echo("done")
// prints
0
1
3
done
The continue statement always applies to the inner-most loop.
Fantom does not support labeled continues.
Switch Statement
Fantom supports a switch statement used to execute a block of
code by matching the value of a expression against a list
of case labels. The syntax is very similar to Java/C#:
switch (<cond>)
{
case <label1>:
<block1>
case <label2>:
<block2>
...
default:
<defaultBlock>
}
The condition expression is matched against all the case labels.
If a match is found, then it executes the statements in that case's
block. If no matches are found then the optional default block
is executed. Unlike the if, for, and while statements, the
case blocks are not wrapped with { } curly braces.
Fantom's switch statement allows the condition and case expressions
to be any valid expressions. So you can switch on strings or types
too. When the condition evaluates to an Int or Enum
and the case labels evaluate to constants, then the switch is
compiled into the tableswitch opcode. Otherwise the switch statement
matches the case labels using an equality check via the Obj.equals
method. For example:
// tableswitch
switch (weekday)
{
case Weekday.sat:
case Weekday.sun:
return "it's the weekend baby!"
default:
return "back to work!"
}
// equality switch
switch (method.upper)
{
case "GET": serviceGet
case "POST": servicePost
default: methodNotSupported
}
In Fantom the switch statement doesn't require a break to end a block
of code for a given case like Java or C#. You cannot fall-through
from one case block to the next case block. However you can group
multiple case labels together like we did with Weekday.sat and Weekday.sun
in the example above.
Exception Handling
Fantom supports throw and try statements with a syntax very similar
to Java and C#. These statements are discussed separately in
the exception handling chapter.