Statements

The most noticeable difference is the use of := to declare a local variable. Fantom uses type inference, so you can omit a local's type declaration. The := operator is used instead of = to show the intention of declaration versus assignment. It prevents silly mistakes like variable name typos.

Fields

Fields automatically include support for accessor methods without a lot of verbosity:

The reason Java and C# programmers write such tortured code is on the off-chance that they want to trap when a field is get or set. In Fantom, fields are always accessed via an auto-generated getter or setter which you can override:

Notice the use of an abstract field. Like interfaces, a mixin can't actually contain any state. But mixins can declare abstract fields which define getters and setters, but no actual storage.

Closures

Fantom supports first class functions and closures - the standard APIs make heavy use of functional programming. Closure syntax kind of, sort of looks like Ruby. For example iteration over collections is almost always done using closures:

Dynamic Programming

Fantom provides some key features to break free from the shackles of strong typing when needed. When you access a field or method using the "." dot operator the compiler does type checking. But you can also use the "->" dynamic call operator to skip type checking:

The "->" operator is really just syntax sugar for invoking the Obj.trap method which by default uses reflection to call a method or access a field. But you can also override the trap method to handle dynamic calls in imaginative ways.

Another feature to make dynamic programming nice is the use of Obj as a wildcard. You can assign Obj to anything or pass it to a method call without an explicit cast:

Nullable Types

Types may be nullable or non-nullable. A non-nullable type is guaranteed to never store the null value. Nullable types are indicated with a trailing "?". This means non-nullable is the default unless otherwise specified:

Str // never stores null
Str? // might store null

The compiler prevents obvious mistakes like using the null literal when a non-nullable type is expected. Additional checks are implicitly done at runtime when coercing a nullable type to a non-nullable type. This allows your code to fail fast at the point where null bug was introduced versus propagating into unrelated code.

Serialization

The serialization syntax of Fantom is a subset of the actual programming language. This means you use serialization to build up arbitrarily complex object structures in code. Plus it makes serialized objects easy for us humans to read and write: