Null object: Difference between revisions

Add Ecstasy example
(→‎{{header|TXR}}: New section.)
(Add Ecstasy example)
Line 714:
 
(f '( a b c)) → a b c
</syntaxhighlight>
 
=={{header|Ecstasy}}==
In Ecstasy, everything is an object, including the <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span> value. <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span> is the only value in the [https://github.com/xtclang/xvm/blob/dd32c2eba0930c4a59f4ba7507c6af37818d255c/lib_ecstasy/src/main/x/ecstasy.x#L21 <span style="background-color: #e5e4e2"><tt>&nbsp;Nullable&nbsp;</tt></span> enumeration defined in the "<tt>ecstasy</tt>" core module]. As a regular old object, the <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span> value has a regular old class, a regular old type, and it implements regular old methods such as <span style="background-color: #e5e4e2"><tt>&nbsp;toString()&nbsp;</tt></span>. There are, however, a few specific ways in the language (both the compiler and runtime) that <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span> is treated specially:
 
<ul><li>Syntax support: A type union with <span style="background-color: #e5e4e2"><tt>&nbsp;Nullable&nbsp;</tt></span> can be indicated with the postfix "?"; for example, the long-hand type union syntax <span style="background-color: #e5e4e2"><tt>&nbsp;Nullable|String s&nbsp;</tt></span> can be replaced using the short-hand notation <span style="background-color: #e5e4e2"><tt>&nbsp;String? s&nbsp;</tt></span>.
</li><li>Syntax support: The postfix "?" operator is a short-circuiting null value test, allowing a cascading sequence of null tests to replace a series of nested if statements; for example, <span style="background-color: #e5e4e2"><tt>&nbsp;Int x = a?.b()?.c?[i?].d? : e;&nbsp;</tt></span> will result in the value of <span style="background-color: #e5e4e2"><tt>&nbsp;e&nbsp;</tt></span> if any of the expressions <span style="background-color: #e5e4e2"><tt>&nbsp;a&nbsp;</tt></span>, <span style="background-color: #e5e4e2"><tt>&nbsp;a.b()&nbsp;</tt></span>, <span style="background-color: #e5e4e2"><tt>&nbsp;a.b().c&nbsp;</tt></span>, <span style="background-color: #e5e4e2"><tt>&nbsp;i&nbsp;</tt></span>, or <span style="background-color: #e5e4e2"><tt>&nbsp;a.b().c[i].d&nbsp;</tt></span> are <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span>.
</li><li>Syntax support: The expression <span style="background-color: #e5e4e2"><tt>&nbsp;x ?: y&nbsp;</tt></span> will use the value <span style="background-color: #e5e4e2"><tt>&nbsp;y&nbsp;</tt></span> iff <span style="background-color: #e5e4e2"><tt>&nbsp;x&nbsp;</tt></span> is <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span>, and the corresponding assignment statement <span style="background-color: #e5e4e2"><tt>&nbsp;x ?:= y&nbsp;</tt></span> will assign <span style="background-color: #e5e4e2"><tt>&nbsp;y&nbsp;</tt></span> to <span style="background-color: #e5e4e2"><tt>&nbsp;x&nbsp;</tt></span> iff <span style="background-color: #e5e4e2"><tt>&nbsp;x&nbsp;</tt></span> is <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span>.
</li><li>Syntax support: The assignment statement <span style="background-color: #e5e4e2"><tt>&nbsp;x ?= y&nbsp;</tt></span> will assign <span style="background-color: #e5e4e2"><tt>&nbsp;y&nbsp;</tt></span> to <span style="background-color: #e5e4e2"><tt>&nbsp;x&nbsp;</tt></span> iff <span style="background-color: #e5e4e2"><tt>&nbsp;y&nbsp;</tt></span> is <b>not</b> <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span>.
</li><li>The assignment operator <span style="background-color: #e5e4e2"><tt>&nbsp;?=&nbsp;</tt></span> also yields a <span style="background-color: #e5e4e2"><tt>&nbsp;Boolean&nbsp;</tt></span> value indicating the <b>non-</b>null-ness the right hand side value, which can be used in an <span style="background-color: #e5e4e2"><tt>&nbsp;if&nbsp;</tt></span> condition, <span style="background-color: #e5e4e2"><tt>&nbsp;while&nbsp;</tt></span> condition, etc.; for example, <span style="background-color: #e5e4e2"><tt>&nbsp;if (x ?= y) ...&nbsp;</tt></span> will take the "then" branch if <span style="background-color: #e5e4e2"><tt>&nbsp;y&nbsp;</tt></span> is non-null and therefore <span style="background-color: #e5e4e2"><tt>&nbsp;x&nbsp;</tt></span> is definitely assigned, otherwise it will take the "else" branch and <span style="background-color: #e5e4e2"><tt>&nbsp;x&nbsp;</tt></span> will not be definitely assigned.
</li><li><span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span> values are treated specially by equality comparisons: Normally, the compiler prevents two references of different compile-time types from being compared (such as <span style="background-color: #e5e4e2"><tt>&nbsp;Int&nbsp;</tt></span> and <span style="background-color: #e5e4e2"><tt>&nbsp;String&nbsp;</tt></span>), but an explicit exception is made that allows a nullable type to be compared with a non-nullable type (such as <span style="background-color: #e5e4e2"><tt>&nbsp;String?&nbsp;</tt></span> and <span style="background-color: #e5e4e2"><tt>&nbsp;String&nbsp;</tt></span>).
</li></ul>
Other than these specific compiler and runtime features, <span style="background-color: #e5e4e2"><tt>&nbsp;Null&nbsp;</tt></span> is treated exactly like every other object.
 
 
<syntaxhighlight lang="java">
module NullObject
{
void run()
{
@Inject Console console;
console.println($"Null value={Null}, Null.toString()={Null.toString()}");
 
// String s = Null; // <-- compiler error: cannot assign Null to a String type
String? s = Null; // "String?" is shorthand for the union "Nullable|String"
String s2 = "test";
console.println($"s={s}, s2={s2}, (s==s2)={s==s2}");
 
// Int len = s.size; // <-- compiler error: String? does not have a "size" property
Int len = s?.size : 0;
console.println($"len={len}");
 
if (String test ?= s)
{
// "s" is still Null in this test, we never get here
}
else
{
s = "a non-null value";
}
 
// s2 = s; // <-- compiler error: a "String?" cannot be assigned to a "String"
if (String test ?= s)
{
// the variable "test" is definitely assigned here
console.println($"test={test}");
}
else
{
// s2 = test; // <-- compiler error: "test" is not definitely assigned
}
}
}
</syntaxhighlight>
 
Output:
<syntaxhighlight>
Null value=Null, Null.toString()=Null
s=Null, s2=test, (s==s2)=False
len=0
test=a non-null value
</syntaxhighlight>
 
162

edits