Expressions

Xtend does not have statements. Instead, everything is an expression and has a return value. That allows to compose your code in interesting ways. For example, you can have a try catch expression on the right hand side of an assignment:

val data = try {
    fileContentsToString('data.txt')
  } catch (IOException e) {
  'dummy data'
  }

If fileContentsToString() throws an IOException, it is caught and the string 'dummy data' is assigned to the value data. Expressions can appear as initializers of fields, the body of constructors or methods and as values in annotations. A method body can either be a block expression or a template expression.

Literals

A literal denotes a fixed unchangeable value. Literals for strings, numbers, booleans, null and Java types are supported.

String Literals

A string literal is of type String (just like in Java). String literals are enclosed in a pair of single quotes or double quotes. We mostly use single quotes because the signal-to-noise ration is a bit better, but generally you should use the terminals which are least likely occure in the actual string. Special characters can be quoted with a backslash or defined using Java's unicode notation. Contrary to Java, strings can span multiple lines.

'Hello World !'
"Hello World !"
'Hello "World" !'
"Hello \"World\" !"
"Hello 

  World !"

Number Literals

Xtend supports roughly the same number literals as Java with a few differences. First, there are no signed number literals. If you put a minus operator in front of an number literal it is taken as a unary operator with one argument (the positive number literal). Second, as in Java 7, you can separate digits using _ for better readability of large numbers. An integer literal creates an int, a long (suffix L) or a BigInteger (suffix BI). There are no octal numbers

42
1_234_567_890 
0xbeef    // hexadecimal
077       // decimal 77 (*NOT* octal)
-1  // an expression consisting of the unary - operator and an integer literal  
42L
0xbeef#L // hexadecimal, mind the '#'
0xbeef_beef_beef_beef_beef#BI // BigInteger

A floating-point literal creates a double (suffix D or none), a float (suffix F) or a BigDecimal (suffix BD). If you use a . you have to specify both, the integer and the fractional part of the mantissa. There are only decimal floating-point literals.

42d     // double
0.42e2  // implicit double
0.42e2f // float
4.2f    // float
0.123_456_789_123_456_789_123_456_789e2000bd // BigDecimal

Boolean Literals

There are two boolean literals, true and false which correspond to their Java counterpart of type boolean.

Null Literal

The null pointer literal null has exactly the same semantics as in Java.

Type Literals

Type literals are specified using the keyword typeof :

typeof(java.lang.String) // yields java.lang.String.class

Type Casts

A type cast behaves exactly like casts in Java, but has a slightly more readable syntax. Type casts bind stronger than any other operator but weaker than feature calls.

The conformance rules for casts are defined in the Java Language Specification. Here are some examples:

something as MyClass
42 as Integer

Although casts are supported you might want to use a switch with a type guard or a dispatch method as a better and safer alternative.

Infix Operators and Operator Overloading

There are a couple of common predefined infix operators. In contrast to Java, the operators are not limited to operations on certain types. Instead an operator-to-method mapping allows users to redefine the operators for any type just by implementing the corresponding method signature. As an example, the Xtend runtime library contains a class BigDecimalExtensions (src) that defines operators for BigDecimals which allows the following code:

val x = 2.71BD
val y = 3.14BD
val sum = x + y    // calls BigDecimalExtension.operator_plus(x,y)

This is the complete list of all available operators and their corresponding method signatures:

e1 += e2 e1.operator_add(e2)
e1 || e2 e1.operator_or(e2)
e1 && e2 e1.operator_and(e2)
e1 == e2 e1.operator_equals(e2)
e1 != e2 e1.operator_notEquals(e2)
e1 < e2 e1.operator_lessThan(e2)
e1 > e2 e1.operator_greaterThan(e2)
e1 <= e2 e1.operator_lessEqualsThan(e2)
e1 >= e2 e1.operator_greaterEqualsThan(e2)
e1 -> e2 e1.operator_mappedTo(e2)
e1 .. e2 e1.operator_upTo(e2)
e1 => e2 e1.operator_doubleArrow(e2)
e1 << e2 e1.operator_doubleLessThan(e2)
e1 >> e2 e1.operator_doubleGreaterThan(e2)
e1 <<< e2 e1.operator_tripleLessThan(e2)
e1 >>> e2 e1.operator_tripleGreaterThan(e2)
e1 <> e2 e1.operator_diamond(e2)
e1 ?: e2 e1.operator_elvis(e2)
e1 <=> e2 e1.operator_spaceship(e2)
e1 + e2 e1.operator_plus(e2)
e1 - e2 e1.operator_minus(e2)
e1 * e2 e1.operator_multiply(e2)
e1 / e2 e1.operator_divide(e2)
e1 % e2 e1.operator_modulo(e2)
e1 ** e2 e1.operator_power(e2)
! e1 e1.operator_not()
- e1 e1.operator_minus()
The table above also defines the operator precedence in ascending order. The blank lines separate precedence levels. The assignment operator += is right-to-left associative in the same way as the plain assignment operator = is. That is a = b = c is executed as a = (b = c), all other operators are left-to-right associative. Parenthesis can be used to adjust the default precedence and associativity.

Short-Circuit Boolean Operators

If the operators || and && are bound to the library methods BooleanExtensions.operator_and(boolean l, boolean r) (src) resp. BooleanExtensions.operator_or(boolean l, boolean r) (src) the operation is evaluated in short circuit mode. That means that the right hand operand might not be evaluated at all in the following cases:

  1. in the case of || the operand on the right hand side is not evaluated if the left operand evaluates to true.
  2. in the case of && the operand on the right hand side is not evaluated if the left operand evaluates to false.

Still you can overload these operators for your types or even override it for booleans, in which case both operands are always evaluated and the defined method is invoked, i.e. no short-circuit execution is happening.

Examples

my.property = 23
myList += 23
x > 23 && y < 23
x && y || z
1 + 3 * 5 * (- 23)
!(x)

Assignments

Local variables can be reassigned using the = operator.

var greeting = 'Hello'
if (isInformal)
  greeting = 'Hi'

Of course, also non-final fields can be set using an assignment:

myObj.myField = 'foo'

Setting Properties

The lack of properties in Java leads to a lot of syntactic noise when working with data objects. As Xtend is designed to integrate with existing Java APIs it respects the Java Beans convention, hence you can call a setter using an assignment:

myObj.myProperty = 'foo' // calls myObj.setMyProperty("foo")

The setter is only used if the field is not accessible from the given context. That is why the @Property annotation would rename the local field to _myProperty.

The return type of an assignment is the type of the right hand side, in case it is a simple assignment. If it is translated to a setter method it yields whatever the setter method returns.

Blocks

The block expression allows to have imperative code sequences. It consists of a sequence of expressions, and returns the value of the last expression. The return type of a block is also the type of the last expression. Empty blocks return null. Variable declarations are only allowed within blocks and cannot be used as a block's last expression.

A block expression is surrounded by curly braces and contains at least one expression. It can optionally be terminated by a semicolon.

Here are two examples:

{
  doSideEffect("foo")
  result
}

{
  var x = greeting
  if (x.equals("Hello ")) {
    x + "World!" 
  } else {
    x
  }
}

Variable Declarations

Variable declarations are only allowed within blocks. They are visible in any subsequent expressions in the block.

A variable declaration starting with the keyword val denotes a value, which is essentially a final (i.e. unsettable) variable. In some cases, one needs to update the value of a reference. In such situations the variable needs to be declared with the keyword var, which stands for 'variable'.

A typical example for using var is a counter in a loop:

{
  val max = 100
  var i = 0
  while (i < max) {
    println("Hi there!")
    i = i + 1
  }
}

Shadowing variables from outer scopes is not allowed, the only exception is the implicit variable it.

Variables declared outside a lambda expression using the var keyword are not accessible from within a lambda expressions.

Typing

The type of the variable itself can either be explicitly declared or be inferred from the right hand side expression. Here is an example for an explicitly declared type:

var List<String> msg = new ArrayList

In such cases, the type of the right hand expression must conform to the type of the expression on the left side.

Alternatively the type can be left out and will be inferred from the initialization expression:

var msg = new ArrayList<String> // -> msg is of type ArrayList<String>  

Field Access and Method Invocation

A simple name can refer to a local field, variable or parameter. In addition it can point to a method with zero arguments, since empty parenthesis are optional.

Property Access

If there is no field with the given name and also no method with the name and zero parameters accessible, a simple name binds to a corresponding Java-Bean getter method if available :

myObj.myProperty // myObj.getMyProperty()  (.. in case myObj.myProperty is not visible.)

Implicit Variables this and it

Like in Java an instance of the class is bound to this. Which allows for either qualifying field access or method invocations like in:

this.myField

or omit the receiver:

myField

You can use the variable name it to get the same behavior for any variable or parameter:

val it = new Person
name = 'Horst' // translates to 'it.setName("Horst");'

Another speciality of the variable it is that it can be shadowed. This is especially useful when used together with lambda expressions.

As this is bound to the surrounding object in Java, it can be used in finer-grained constructs such as lambda expressions. That is why it.myProperty has higher precedence than this.myProperty.

Static Access

For accessing a static field or method you have to use the double colon :: like in this example:

MyClass::myField
MyClass::myMethod('foo')

Alternatively you could import the method using a static import.

Null-Safe Feature Call

Checking for null references can make code very unreadable. In many situations it is ok for an expression to return null if a receiver was null. Xtend supports the safe navigation operator ?. to make such code better readable.

Instead of writing

if (myRef != null) myRef.doStuff()

one can write

myRef?.doStuff

Constructor Call

Constructor calls have the same syntax as in Java. The only difference is that empty parenthesis are optional:

new String() == new String
new ArrayList<BigDecimal>() == new ArrayList<BigDecimal>

Lambda Expressions

A lambda expression is basically a piece of code, which is wrapped in an object to pass it around. As a Java developer it is best to think of a lambda expression as an anonymous class, i.e. like in the following Java code :

// Java Code!
final JTextField textField = new JTextField();
textField.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    textField.setText("Something happened!");
  }
});

This kind of anonymous classes can be found everywhere in Java code and have always been the poor-man's replacement for lambda expressions in Java.

Xtend not only supports lambda expressions, but offers an extremely dense syntax for it. That is the code above can be written in Xtend like this:

val textField = new JTextField
textField.addActionListener([ ActionEvent e |
  textField.text = "Something happened!"
])

As you might have guessed, a lambda expression is surrounded by square brackets (inspired from Smalltalk). Also a lambda expression like a method declares parameters. The lambda above has one parameter called e which is of type ActionEvent. You do not have to specify the type explicitly because it can be inferred from the context:

textField.addActionListener([ e |
  textField.text = "Something happened!"
])

Also as lambdas with one parameter are a common case, there is a special short hand for them, which is to leave the declaration including the vertical bar out. The name of the single variable will be it in that case:

textField.addActionListener([
  textField.text = "Something happened!"
])

A lambda expression with zero arguments is written like this (note the bar after the opening bracket):

val Runnable runnable = [ |
  println("Hello I'm executed!")
]

When a method call's last parameter is a lambda it can be passed right after the parameter list. For instance if you want to sort some strings by their length, you could write :

Collections::sort(someStrings) [ a, b |
  a.length - b.length
]

which is just the same as writing

Collections::sort(someStrings, [ a, b |
  a.length - b.length
])

Since you can leave out empty parenthesis for methods which get a lambda as their only argument, you can reduce the code above further:

textField.addActionListener [
  textField.text = "Something happened!"
]

A lambda expression also captures the current scope, so that any final variables and parameters visible at construction time can be referred to in the closure's expression. That is exactly what we did with the variable textField.

Typing

Lambdas are expressions which produce Function objects. The type of a lambda expression generally depends on the target type, as seen in the previous examples. That is, the lambda expression can coerce to any interface which has declared only one method (in addition to the ones inherited from Object). This allows for using lambda expressions in many existing Java APIs directly.

However, if you write a lambda expression without having any target type expectation, like in the following assignment:

val toUpperCaseFunction = [ String s | s.toUpperCase ] // inferred type is (String)=>String

The type will be one of the types found in Functions (src) or Procedures (src). It is a procedure if the return type is void, otherwise it is a function.

Xtend supports a shorthand syntax for function types. Instead of writing Function1<? super String,? extends String> which is what you will find in the generated Java code, you can simply write (String)=>String.

Example:

val (String)=>String stringToStringFunction = [ toUpperCase ]
// or
val Function1<? super String,? extends String> same = [ toUpperCase ]
// or
val stringToStringFunction2 = [ String s | s.toUpperCase ] // inferred type is (String)=>String

Checked exceptions that are thrown in the body of a closure but not declared in the implemented method of the target type are rethrown using the sneaky-throw technique. Of course you can always catch and handle them.

If Expression

An if expression is used to choose between two different values based on a predicate.

An expression

if (p) e1 else e2

results in either the value e1 or e2 depending on whether the predicate p evaluates to true or false. The else part is optional which is a shorthand for else null. That means

if (foo) x 

is a short hand for

if (foo) x else null

The type of an if expression is the common super type of the return types T1 and T2 of the two expression e1 and e2.

While the if expression has the syntax of Java's if statement it behaves more like Java's ternary operator (predicate ? thenPart : elsePart), because it is an expression and returns a value. Consequently, you can use if expressions deeply nested within expressions:

val name = if (firstName != null) firstName + ' ' + lastName else lastName

Switch Expression

The switch expression is very different from Java's switch statement. First, there is no fall through which means only one case is evaluated at most. Second, the use of switch is not limited to certain values but can be used for any object reference instead. Object.equals(Object) is used to compare the value in the case with the one you are switching over. Given the following example:

switch myString {
  case myString.length>5 : "a long string."
  case 'some' : "It's some string."
  default : "It's another short string."
}

the main expression numberAsText is evaluated first and then compared to each case sequentially. If the case expression is of type boolean, the case matches if the expression evaluates to true. If it is not of type boolean it is compared to the value from the main expression using Object.equals(Object).

If a case is a match, that is it evaluates to true or the result equals the one we are switching over, the case expression after the colon is evaluated and is the result of the whole expression.

Type guards

Instead of or in addition to the case guard you can specify a type guard. The case only matches if the switch value conforms to this type. A case with both a type guard and a predicate only matches if both match. If the switch value is a variable, this variable is automatically casted to the given type within the predicate and the case's body.

def length(Object x) {
  switch x {
    String case x.length > 0 : x.length // length is defined for String 
    List<?> : x.size    // size is defined for List
    default : -1
  }
}

Switches with type guards are a safe and much more readable alternative to instance of / casting orgies you might know from Java.

For Loop

The for loop

for (T1 variable : arrayOrIterable) expression

is used to execute a certain expression for each element of an array or an instance of Iterable. The local variable is final, hence canot be updated.

The return type of a for loop is void. The type of the local variable can be left out. In that case it is inferred from the type of the array or java.lang.Iterable returned by the iterable expression.

for (String s : myStrings) {
  doSideEffect(s)
}

for (s : myStrings)
  doSideEffect(s)

While Loop

A while loop

while (predicate) expression

is used to execute a certain expression unless the predicate is evaluated to false. The return type of a while loop is void.

while (true) {
  doSideEffect("foo")
}

while ((i=i+1) < max) 
  doSideEffect("foo")

Do-While Loop

A do-while loop

do expression while (predicate)

is used to execute a certain expression until the predicate is evaluated to false. The difference to the while loop is that the execution starts by executing the block once before evaluating the predicate for the first time. The return type of a do-while loop is void.

do {
  doSideEffect("foo");
while (true)


do doSideEffect("foo"while ((i=i+1)<max)

Return Expression

A method or lambda expression automatically returns the value of its expression. If it is a block expression this is the value of the last expression in it. However, sometimes you want to return early or make it explicit.

The syntax is just like in Java:

listOfStrings.map(e| {
  if (e==null
    return "NULL"
  e.toUpperCase
}) 

Throwing Exceptions

Throwing Throwables up the call stack has the same semantics and syntax as in Java.

{
  ...
  if (myList.isEmpty)
    throw new IllegalArgumentException("the list must not be empty")
  ...
}

Try, Catch, Finally

The try-catch-finally expression is used to handle exceptional situations. Checked exceptions are treated like runtime exceptions. You can but do not have to catch them as they will be silently rethrown (see the section on declared exceptions). The syntax again is like Java.

try {
  throw new RuntimeException()
catch (NullPointerException e) {
  // handle e
finally {
  // do stuff
}

For try-catch it is again beneficial that it is an expression, because you can write code like the following and do not have to rely on non-final variables:

val name = try {
    person.name
  } catch (NullPointerException e) {
    "no name"
  }

Template Expressions

Templates allow for readable string concatenation. Templates are surrounded by triple single quotes ('''). A template expression can span multiple lines and expressions can be nested which are evaluated and their toString() representation is automatcially inserted at that position.

The terminals for interpolated expression are so called guillemets «expression». They read nicely and are not often used in text so you seldomly need to escape them. These escaping conflicts are the reason why template languages often use longer character sequences like e.g. <%= expression %> in JSP, for the price of worse readability. The downside with the guillemets in Xtend is that you will have to have a consistent encoding. Always use UTF-8 and you are good.

If you use the Eclipse plug-in - which is recommended - the guillemets will be inserted on content assist within a template. They are additionally bound to CTRL+SHIFT+< and CTRL+SHIFT+ for « and » respectively. On a Mac they are as well bound to alt+q («) and alt+Q (»).

Let us have a look at an example of how a typical method with a template expressions looks like:

def someHTML(String content) '''
  <html>
    <body>
      «
content»
    </body>
  </html>
'''

As you can see, template expressions can be used as the direct body of a method. If an interpolation expression evaluates to null an empty string is added.

Template expressions can occur everywhere. Here is an example showing it in conjunction with the powerful switch expression:

def toText(Node n) {
  switch n {
    Contents : n.text

    A : '''<a href="«n.href»">«n.applyContents»</a>'''

    default : '''
        <«
n.tagName»>
          «
n.applyContents»
        </«
n.tagName»>
    '''

  }
}

Conditions in Templates

There is a special IF to be used within templates:

def someHTML(Paragraph p) '''
  <html>
    <body>
      «
IF p.headLine != null»
        <h1>«
p.headline»</h1>
      «
ENDIF»
      <p>
        «
p.text»
      </p>
    </body>
  </html>
'''

Loops in Templates

Also a FOR statement is available:

def someHTML(List<Paragraph> paragraphs) '''
  <html>
    <body>
      «
FOR p : paragraphs»
        «
IF p.headLine != null»
          <h1>«
p.headline»</h1>
        «
ENDIF»
        <p>
          «
p.text»
        </p>
      «
ENDFOR»
    </body>
  </html>
'''

The for statement optionally allows to specify what to prepend (BEFORE), put in-between (SEPARATOR), and what to put at the end (AFTER) of all iterations. BEFORE and AFTER are only executed if there is at least one iteration. (SEPARATOR) is only added between iterations, that it is executed if there are at least two iterations.

Here is an example:

def someHTML(List<Paragraph> paragraphs) '''
  <html>
    <body>
      «
FOR p : paragraphs BEFORE '<div>' SEPARATOR '</div><div>' AFTER '</div>'»
        «
IF p.headLine != null»
          <h1>«
p.headline»</h1>
        «
ENDIF»
        <p>
          «
p.text»
        </p>
      «
ENDFOR»
    </body>
  </html>
'''

Typing

The template expression is of type CharSequence. It is automatically converted to String if that is the expected target type.

White Space Handling

One of the key features of templates is the smart handling of white space in the template output. The white space is not written into the output data structure as is but preprocessed. This allows for readable templates as well as nicely formatted output. The following three rules are applied when the template is evaluated:

  1. Indentation in the template that is relative to a control structure will not be propagated to the output string. A control structure is a FOR-loop or a condition (IF) as well as the opening and closing marks of the template string itself. The indentation is considered to be relative to such a control structure if the previous line ends with a control structure followed by optional white space. The amount of white space is not taken into account but the delta to the other lines.
  2. Lines that do not contain any static text which is not white space but do contain control structures or invocations of other templates which evaluate to an empty string, will not appear in the output.
  3. Any newlines in appended strings (no matter they are created with template expressions or not) will be prepended with the current indentation when inserted.

Although this algorithm sounds a bit complicated at first it behaves very intuitively. In addition the syntax coloring in Eclipse communicates this behavior.

Syntax Coloring For Templates In Eclipse

The behavior is best described with a set of examples. The following table assumes a data structure of nested nodes.

class Template {
  def print(Node n) '''
    node «
n.name» {}
  '''

}

node NodeName {}

The indentation before node «n.name» will be skipped as it is relative to the opening mark of the template string and thereby not considered to be relevant for the output but only for readability of the template itself.

class Template {
  def print(Node n) '''
    node «
n.name» {
      «
IF hasChildren»
        «
n.children.map[print]»
      «
ENDIF»
    }
  '''

}

node Parent{
  node FirstChild {
  }
  node SecondChild {
    node Leaf {
    }
  }
}

As in the previous example, there is no indentation on the root level for the same reason. The first nesting level has only one indentation level in the output. This is derived from the indentation of the IF hasChildren condition in the template which is nested in the node. The additional nesting of the recursive invocation children.map[print] is not visible in the output as it is relative the the surrounding control structure. The line with IF and ENDIF contain only control structures thus they are skipped in the output. Note the additional indentation of the node Leaf which happens due to the first rule: Indentation is propagated to called templates.