Conditions and condition lists

Usage

Special form conditions and condition lists are supported by the if, while, assert statements and if comprehensions

Note: This page is not describing the is, exists and nonempty operators.

Description

We shall use if for the purposes of illustration, but the same constructs apply to while and assert statements.

if (is ...)

if (is X x) is a condition that tests whether a value or variable x is assignable to the type X. Within the associated block x will have the type X.

In other words, if (is ...) is similar Java's instanceof operator with a suitable typecast occurring automatically within the block. Here's a simple example

Integer plusOneIfInteger(Object x) {
    if (is Integer x) {
        // x of type Integer here
        return = x+1;
    }
    return 0;
} 

It is also possible to introduce a new local attribute in the condition, in which case it is the new local attribute that has the narrowed type:

Integer plusOneIfInteger(Object x) {
    if (is Integer y=x) {
        // x still of type Object here
        // but y is Integer
        return y+1;
    }
    return 0;
} 

if (is ...) is more sophistocated than a Java instanceof though, because it inderstand parameterized types: You can say if (is List<Integer> list) to distinguish a List<Integer> from a List<String>.

Note: Do not confuse the is condition described here and which takes the form is Type attribute with the is operator which takes form attribute is Type.

if (exists ...)

if (exists x) is equivalent to if (is X x) where x is an expression of type X?. Within the associated block x will have the type X.

In other words if (exists ...) is similar to a if (x != null) null check in Java.

Here's an example

Integer plusOneIfExists(Integer? x) {
    if (exists x) {
        // x of type Integer here
        return x+1;
    }
    return 0;
} 

It is also possible to introduce a new local attribute in the condition, in which case it is the new local attribute that has the narrowed type:

Integer plusOneIfExists(Integer? x) {
    if (exists y=x) {
        // x still of type Integer? here
        return y+1;
    }
    return 0;
} 

Note: Do not confuse the exists condition described here and which takes the form exists attribute with the exists operator which takes form attribute exists.

if (nonempty ...)

if (nonempty x) is equivalent to whether the subtype of Anything[]? when intersected with [] is not Nothing, and when intersected with [Nothing+] is not Nothing. Within the associated block x will have the type E

Here's an example

Integer firstPlusOne(Integer[] x) {
    if (nonempty x) {
        // x of type Integer[] here
        return x.first+1;
    }
    return 0;
} 

It is also possible to introduce a new local attribute in the condition, in which case it is the new local attribute that has the narrowed type:

Integer firstPlusOne(Integer[] x) {
    if (nonempty y=x) {
        // x still of type Integer[] here
        return y.first+1;
    }
    return 0;
} 

Note: Do not confuse the nonempty condition described here and which takes the form nonempty attribute with the nonempty operator which takes form attribute nonempty.

if (satisfies ...)

Ceylon 1.1 or later

if (satisfies X Y) is a condition that tests whether the type Y is a subtype of the type X. within the associated block Y will be treated as a subtype of X.

Condition lists

Ceylon supports having multiple conditions (called a condition list) in if, while, assert statements and in if comprehensions.

A condition list evaluates as true when all conditions in the list evaluate as true. The difference between a condition list and a single Boolean condition constructed using the && operator is that any special form conditions in the list take effect for conditions later in the list, allowing you to write:

Integer m(Object x) {
    if (is Integer x, x < 10) {
        // x is of type Integer here
        return x + 1;
    }
    return 0;
}

See also