# ExpressionsExpression

## Expressions

The expression sub-language is a syntactical mixture of Java and OCL. This documentation provides a detailed description of each available expression. Let us start with some simple examples.

Accessing a property:

    myModelElement.name

Accessing an operation:

    myModelElement.doStuff()

simple arithmetic:

    1 + 1 * 2

boolean expressions (just an example:-)):

    !('text'.startsWith('t') && ! false)

### Literals and special operators for built-in types

There are several literals for built-in types:

#### `Object`

There are naturally no literals for object, but we have two operators:

equals:

    obj1 == obj2

not equals:

    obj1 != obj2

#### `Void`

The only possible instance of `Void` is the `null` reference. Therefore, we have one literal:

    null

#### Type literals

The literal for types is just the name of the type (no '.class' suffix, etc.). Example:

    String // the type string
    my::special::Type // evaluates to the type 'my::special::Type'

#### StaticProperty literals

The literal for static properties (aka enum literals) is correlative to type literals:

    my::Color::RED

#### `String`

There are two different literal syntaxes (with the same semantics):

    'a String literal'
    "a String literal" // both are okay

For Strings the expression sub-language supports the plus operator that is overloaded with concatenation:

    'my element '+ ele.name +' is really cool!'

Note, that multi-line Strings are supported.

#### `Boolean`

The boolean literals are:

    true
    false

Operators are:

    true && false // AND
    true || false // OR
    ! true        // NOT

#### `Integer` and `Real`

The syntax for integer literals is as expected:

    // integer literals
    3
    57278
    // real literals
    3.0
    0.75

Additionally, we have the common arithmetic operators:

    3 + 4  // addition
    4 - 5  // subtraction
    2 * 6  // multiplication
    3 / 64 // divide
    // Unary minus operator
    - 42
    - 47.11

Furthermore, the well known compare operators are defined:

    4 > 5 // greater than
    4 < 5 // smaller than
    4 >= 23 // greater equals than
    4 <= 12 // smaller equals than

#### Collections

There is a literal for lists:

    {1,2,3,4} // a list with four integers

There is no other special concrete syntax for collections. If you need a set, you have to call the `toSet()` operation on the list literal:

    {1,2,4,4}.toSet() // a set with 3(!) integers

### Special Collection operations

Like OCL, the Xpand expression sub-language defines several special operations on collections. However, those operations are not members of the type system, therefore you cannot use them in a reflective manner.

#### `select`

Sometimes, an expression yields a large collection, but one is only interested in a special subset of the collection. The expression sub-language has special constructs to specify a selection out of a specific collection. These are the `select` and `reject` operations. The select specifies a subset of a collection. A `select` is an operation on a collection and is specified as follows:

    collection.select(v | boolean-expression-with-v)

`select` returns a sublist of the specified collection. The list contains all elements for which the evaluation of boolean-expression-with-v results is `true`. Example:

    {1,2,3,4}.select(i | i >= 3) // returns {3,4}

#### `typeSelect`

A special version of a select expression is `typeSelect`. Rather than providing a boolean expression a class name is here provided.

    collection.typeSelect(classname)

`typeSelect` returns that sublist of the specified collection, that contains only objects which are an instance of the specified class (also inherited).

#### `reject`

The `reject` operation is similar to the `select` operation, but with `reject` we get the subset of all the elements of the collection for which the expression evaluates to `false`. The `reject` syntax is identical to the `select` syntax:

    collection.reject(v | boolean-expression-with-v)

Example:

    {1,2,3,4}.reject(i | i >= 3) // returns {1,2}

#### `collect`

As shown in the previous section, the `select` and `reject` operations always result in a sub-collection of the original collection. Sometimes one wants to specify a collection which is derived from another collection, but which contains objects that are not in the original collection (it is not a sub-collection). In such cases, we can use a `collect` operation. The `collect` operation uses the same syntax as the `select` and `reject` and is written like this:

    collection.collect(v | expression-with-v)

`collect` again iterates over the target collection and evaluates the given expression on each element. In contrast to `select`, the evaluation result is collected in a list. When an iteration is finished the list with all results is returned. Example:

    namedElements.collect(ne | ne.name) // returns a list of strings

#### Shorthand for `collect` (and more than that)

As navigation through many objects is very common, there is a shorthand notation for collect that makes the expressions more readable. Instead of

    self.employee.collect(e | e.birthdate)

one can also write:

    self.employee.birthdate

In general, when a property is applied to a collection of Objects, it will automatically be interpreted as a `collect` over the members of the collection with the specified property.

The syntax is a shorthand for `collect`, if the feature does not return a collection itself. But sometimes we have the following:

    self.buildings.rooms.windows // returns a list of windows

This syntax works, but one cannot express it using the `collect` operation in an easy way.

#### `forAll`

Often a boolean expression has to be evaluated for all elements in a collection. The `forAll` operation allows specifying a Boolean expression, which must be `true`for all objects in a collection in order for the `forAll` operation to return `true`:

    collection.forAll(v | boolean-expression-with-v)

The result of `forAll` is `true` if `boolean-expression-with-v` is `true` for all the elements contained in a collection. If `boolean-expression-with-v` is `false` for one or more of the elements in the collection, then the `forAll` expression evaluates to `false`.

Example:

    {3,4,500}.forAll(i | i < 10) // evaluates to false (500 < 10 is false)

#### `exists`

Often you will need to know whether there is at least one element in a collection for which a boolean is `true`. The exists operation allows you to specify a Boolean expression which must be `true` for at least one object in a collection:

    collection.exists(v | boolean-expression-with-v)

The result of the exists operation is `true` if `boolean-expression-with-v` is `true` for at least one element of collection. If the `boolean-expression-with-v` is `false` for all elements in collection, then the complete expression evaluates to `false`.

Example:

    {3,4,500}.exists(i | i < 10) // evaluates to true (e.g. 3 < 10 is true)

#### `sortBy` [1]

If you want to sort a list of elements, you can use the higher order function `sortBy` . The list you invoke the `sortBy` operation on, is sorted by the results of the given expression.

Example:

    myListOfEntity.sortBy(entity | entity.name)

In the example the list of entities is sorted by the name of the entities. Note that there is no such `Comparable` type in Xpand . If the values returned from the expression are instances of `java.util.Comparable` the `compareTo` method is used, otherwise `toString()` is invoked and the the result is used.

More Examples â€“ all the following expressions return `true`:

    {'C','B','A'}.sortBy(e | e) == {'A','B','C'}
    {'AAA','BB','C'}.sortBy(e | e.length) == {'C','BB','AAA'}
    {5,3,1,2}.sortBy(e | e) == {1,2,3,5}
    {5,3,1,2}.sortBy(e | e - 2 * e) == {5,3,2,1}
    ...

### `if` expression

There are two different forms of conditional expressions. The first one is the so-called if expression . Syntax:

    condition ? thenExpression : elseExpression

Example:

    name != null ? name : 'unknown'

Alternatively, you also could write:

          if name != null then
             name
          else
            'unknown'

### `switch` expression

The other one is called switch expression . Syntax:

    switch (expression) {
       (case expression : thenExpression)*
       default : catchAllExpression
    }

The default part is mandatory, because `switch` is an expression, therefore it needs to evaluate to something in any case. Example:

    switch (person.name) {
       case 'Hansen' : 'Du kanns platt schnacken'
       default : 'Du kanns mi nech verstohn!'
    }

There is an abbreviation for Boolean expressions:

    switch {
       case booleanExpression : thenExpression
       default : catchAllExpression
    }

### Chain expression

Expressions and functional languages should be free of side effects as far as possible. But sometimes there you need invocations that do have side effects. In some cases expressions even don not have a return type (i.e. the return type is `Void`). If you need to call such operations, you can use the chain expression. Syntax:

    anExpr ->
    anotherExpr ->
    lastExpr

Each expression is evaluated in sequence, but only the result of the last expression is returned. Example:

    pers.setName('test') ->
    pers

This chain expression will set the `name` of the person first, before it returns the person object itself.

### `create` expression

The `create` expression is used to instantiate new objects of a given type:

    new TypeName

### `let` expression

The `let` expression lets you define local variables. Syntax is as follows:

    let v = expression : expression-with-v

This is especially useful together with a chain- and a create expressions. Example:

    let p = new Person :
       p.name('John Doe') ->
       p.age(42) ->
       p.city('New York') ->
       p

### 'GLOBALVAR' expression

Sometimes you don't want to pass everything down the call stack by parameter. Therefore, we have the `GLOBALVAR` expression. There are two things you need to do, to use global variables.

#### Using GLOBALVARS to configure workflows

Each workflow component using the expression framework ( Xpand , Check and Xtend ) can be configured with global variables. Here is an example:

    <workflow>
       .... stuff
       <component class="org.eclipse.xpand2.Generator">
          ... usual stuff (see ref doc)
          <globalVarDef name="MyPSM" value="slotNameOfPSM"/>
          <globalVarDef name="ImplClassSuffix" value="'Impl'"/>
       </component>
    </workflow>

If you have injected global variables into the respective component, you can call them using the following syntax:

    GLOBALVAR ImplClassSuffix

Note, we don't have any static type information. Therefore `Object` is assumed. So, you have to down cast the global variable to the intended type:

    ((String) GLOBALVAR ImplClassSuffix)

It is good practice to type it once, using an Extension and then always refer to that extension:

    String implClassSuffix() : GLOBALVAR ImplClassSuffix;
    // usage of the typed global var extension
    ImplName(Class c) :
       name+implClassSuffix();

### Multi methods (multiple dispatch)

The expressions language supports multiple dispatching . This means that when there is a bunch of overloaded operations, the decision which operation has to be resolved is based on the dynamic type of all parameters (the implicit '`this`' included).

In Java only the dynamic type of the '`this`' element is considered, for parameters the static type is used. (this is called single dispatch)

Here is a Java example:

    class MyClass {
       boolean equals(Object o) {
          if (o instanceof MyClass) {
             return equals((MyClass)o);
          }
          return super.equals(o);
       }
       boolean equals(MyType mt) {
          //implementation...
       }
    }

The method `equals(Object o)` would not have to be overwritten, if Java would support multiple dispatch.

### Casting

The expression language is statically type checked. Although there are many concepts that help the programmer to have really good static type information, sometimes. one knows more about the real type than the system. To explicitly give the system such an information casts are available. Casts are 100% static, so you do not need them, if you never statically typecheck your expressions!

The syntax for casts is very Java-like:

    ((String)unTypedList.get(0)).toUpperCase()

[1] since 4.1.2