Safe Null Handling in Ceylon: exists, else, and nonempty
Ceylon rejects direct dereference of nullable types. Use exists, else, and nonempty to handle null safely, with scoping limits and toolchain checks.
13 Sept 2026, 02:27 UTC

The problem: nullable references cannot be dereferenced directly
In Ceylon, a type written with a postfix question mark, such as String?, is a nullable type. It can hold either a string or null. The compiler treats String? as a different type from String, so code like name.size fails to compile when name is declared as String?. You must prove to the compiler that the value is not null before reading its members.
Useful takeaway
Use exists to refine a nullable value into a non-null binding inside a block. Use else to supply a default when the value is null. Use nonempty before calling first or last on a sequence. The exists binding applies only inside its block; the original variable remains nullable afterward.
Worked example: looking up a value
The following representative example shows a lookup that may return null. The syntax reflects Ceylon 1.3.x patterns; confirm exact spelling against the Ceylon language reference for your installed toolchain.
String? lookup(String key) => null;
void run() {
// This line does not compile: lookup returns String?,
// and String? cannot be dereferenced without a check.
// print(lookup("user").size);
if (exists value = lookup("user")) {
print("Found: " + value.size);
}
String label = lookup("user") else "unknown";
print("Label: " + label);
}
The commented line is a compile-time error because the compiler refuses to dereference a nullable reference. The exists block introduces value as a non-null String only within that block, so value.size compiles. The else expression yields "unknown" when the lookup returns null, and the actual string otherwise.
Comparison of null-handling operators
| Operator | Purpose | Result when null | Scope of refined binding |
|---|---|---|---|
exists | Refines nullable to non-null inside a block | Block body is skipped | Block only |
else | Supplies a default value | Returns the default expression | Expression only |
nonempty | Refines a sequence to guarantee at least one element | Access is guarded or skipped | Block or expression |
Verify with the Ceylon toolchain
Run these commands from the directory that contains your source file. Ordinary user permissions are sufficient for a local compile; do not run the compiler as root unless file ownership requires it.
ceylon compile --help— confirms the compiler is installed and lists supported options.ceylon compile .ceylon— compiles the example. The unchecked dereference should fail; theexistsandelseblocks should compile.ceylon run— runs the compiled module. Whenlookupreturns null, theelsebranch prints the default value.
Expected checks: the compiler rejects direct member access on a nullable type; exists narrows the type inside its block; else supplies the fallback on null. Risk: syntax errors if your installed Ceylon version does not match the example.
Limits and common mistakes
existsscopes the refined binding to its block. After the block ends, the outer variable is still nullable.- Ceylon does not implicitly convert
String?toString. Useexists,else, or another explicit check. nonemptyguardsfirstandlaston sequences. Calling them without the check on an empty sequence is unsafe.- Ceylon 1.3.x is the last major release line, and active Red Hat development has ended. Confirm JDK and toolchain support before starting a new project.
Practical check
Create a file named lookup.ceylon, paste the example, then run ceylon compile lookup.ceylon. Comment out the unchecked dereference line, recompile, and confirm success. Run the module and verify that the default appears when the lookup returns null and the real value appears when it returns a string.
This draft describes established Ceylon 1.3.x null-safety patterns. JDK compatibility and current toolchain availability require verification before production use.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.