Null object: Difference between revisions
Content added Content deleted
(→{{header|TXR}}: New section.) |
(Add Ecstasy example) |
||
Line 714: | Line 714: | ||
(f '( a b c)) → a b c |
(f '( a b c)) → a b c |
||
</syntaxhighlight> |
|||
=={{header|Ecstasy}}== |
|||
In Ecstasy, everything is an object, including the <span style="background-color: #e5e4e2"><tt> Null </tt></span> value. <span style="background-color: #e5e4e2"><tt> Null </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> Nullable </tt></span> enumeration defined in the "<tt>ecstasy</tt>" core module]. As a regular old object, the <span style="background-color: #e5e4e2"><tt> Null </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> toString() </tt></span>. There are, however, a few specific ways in the language (both the compiler and runtime) that <span style="background-color: #e5e4e2"><tt> Null </tt></span> is treated specially: |
|||
<ul><li>Syntax support: A type union with <span style="background-color: #e5e4e2"><tt> Nullable </tt></span> can be indicated with the postfix "?"; for example, the long-hand type union syntax <span style="background-color: #e5e4e2"><tt> Nullable|String s </tt></span> can be replaced using the short-hand notation <span style="background-color: #e5e4e2"><tt> String? s </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> Int x = a?.b()?.c?[i?].d? : e; </tt></span> will result in the value of <span style="background-color: #e5e4e2"><tt> e </tt></span> if any of the expressions <span style="background-color: #e5e4e2"><tt> a </tt></span>, <span style="background-color: #e5e4e2"><tt> a.b() </tt></span>, <span style="background-color: #e5e4e2"><tt> a.b().c </tt></span>, <span style="background-color: #e5e4e2"><tt> i </tt></span>, or <span style="background-color: #e5e4e2"><tt> a.b().c[i].d </tt></span> are <span style="background-color: #e5e4e2"><tt> Null </tt></span>. |
|||
</li><li>Syntax support: The expression <span style="background-color: #e5e4e2"><tt> x ?: y </tt></span> will use the value <span style="background-color: #e5e4e2"><tt> y </tt></span> iff <span style="background-color: #e5e4e2"><tt> x </tt></span> is <span style="background-color: #e5e4e2"><tt> Null </tt></span>, and the corresponding assignment statement <span style="background-color: #e5e4e2"><tt> x ?:= y </tt></span> will assign <span style="background-color: #e5e4e2"><tt> y </tt></span> to <span style="background-color: #e5e4e2"><tt> x </tt></span> iff <span style="background-color: #e5e4e2"><tt> x </tt></span> is <span style="background-color: #e5e4e2"><tt> Null </tt></span>. |
|||
</li><li>Syntax support: The assignment statement <span style="background-color: #e5e4e2"><tt> x ?= y </tt></span> will assign <span style="background-color: #e5e4e2"><tt> y </tt></span> to <span style="background-color: #e5e4e2"><tt> x </tt></span> iff <span style="background-color: #e5e4e2"><tt> y </tt></span> is <b>not</b> <span style="background-color: #e5e4e2"><tt> Null </tt></span>. |
|||
</li><li>The assignment operator <span style="background-color: #e5e4e2"><tt> ?= </tt></span> also yields a <span style="background-color: #e5e4e2"><tt> Boolean </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> if </tt></span> condition, <span style="background-color: #e5e4e2"><tt> while </tt></span> condition, etc.; for example, <span style="background-color: #e5e4e2"><tt> if (x ?= y) ... </tt></span> will take the "then" branch if <span style="background-color: #e5e4e2"><tt> y </tt></span> is non-null and therefore <span style="background-color: #e5e4e2"><tt> x </tt></span> is definitely assigned, otherwise it will take the "else" branch and <span style="background-color: #e5e4e2"><tt> x </tt></span> will not be definitely assigned. |
|||
</li><li><span style="background-color: #e5e4e2"><tt> Null </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> Int </tt></span> and <span style="background-color: #e5e4e2"><tt> String </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> String? </tt></span> and <span style="background-color: #e5e4e2"><tt> String </tt></span>). |
|||
</li></ul> |
|||
Other than these specific compiler and runtime features, <span style="background-color: #e5e4e2"><tt> Null </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> |
</syntaxhighlight> |
||