Null object: Difference between revisions

10,581 bytes added ,  2 months ago
No edit summary
(14 intermediate revisions by 7 users not shown)
Line 715:
(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.print($"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.print($"{s=}, {s2=}, {s==s2=}");
 
// Int len = s.size; // <-- compiler error: String? does not have a "size" property
Int len = s?.size : 0;
console.print($"{len=}");
 
if (String test ?= s) {
// "s" is still Null in this test, we never get here
} else {
s = "a non-null value";
}
 
// if (String test ?= s){} // <-- compiler error: The expression type is not nullable
s2 = s; // at this point, s is known to be a non-null String
console.print($"{s=}, {s2=}, {s==s2=}");
}
}
</syntaxhighlight>
 
{{out}}
<pre>
Null value=Null, Null.toString()=Null
s=Null, s2=test, s==s2=False
len=0
s=a non-null value, s2=a non-null value, s==s2=True
</pre>
 
=={{header|Eiffel}}==
Line 754 ⟶ 803:
<syntaxhighlight lang="elixir">iex(3)> if nil, do: "not execute"
nil</syntaxhighlight>
 
=={{header|EMal}}==
<syntaxhighlight lang="emal">
^|
| EMal has the Variable type (and its keyword var) that is the nullable universal supertype.
| EMal has the Void type (and its keyword void) that holds only one value: null.
| EMal has not nullable types (logic, int, real, text, blob), but null equality is always allowed.
|^
var a # defaults to null
int b # defaults to 0
void c # only one allowed value: null
writeLine("nullable var equals to not nullable int: " + (a == b)) # allowed, false
^| if the data type of a is void we are sure that a is null |^
writeLine("type of a equals to Void data type: " + (generic!a == void)) # true
writeLine("integer value " + b + " equals to null: " + (b == null)) # allowed, always false
writeLine("a void value equals to null: " + (c == null)) # always true</syntaxhighlight>
{{out}}
<pre>
nullable var equals to not nullable int: ⊥
type of a equals to Void data type: ⊤
integer value 0 equals to null: ⊥
a void value equals to null: ⊤
</pre>
 
=={{header|Erlang}}==
Line 862 ⟶ 934:
</pre>
 
=={{header|GDScript}}==
Godot has a null value. Here is an example of dealing with null.
<syntaxhighlight lang="gdscript">
extends Node2D
 
func _ready() -> void:
var empty : Object
var not_empty = Object.new()
# Compare with null.
if empty == null:
print("empty is null")
else:
print("empty is not null")
# C-like comparation.
if not_empty:
print("not_empty is not null")
else:
print("not_empty is null")
return
</syntaxhighlight>
{{out}}
<pre>
empty is null
not_empty is not null
</pre>
 
=={{header|Go}}==
Line 1,091 ⟶ 1,189:
 
=={{header|langur}}==
Null can be compared for directly, using equality operators, or can be checked with the isNull() function. Operators ending with a ? mark propagate null. A null in an expression test is a non-truthy result.
 
{{works with|langur|0.10}}
Prior to 0.10, multi-variable declaration/assignment would use parentheses around variable names and values.
 
<syntaxhighlight lang="langur">val .x, .y = true, null
Line 1,393 ⟶ 1,488:
=={{header|MAXScript}}==
<syntaxhighlight lang="maxscript">if obj == undefined then print "Obj is undefined"</syntaxhighlight>
 
=={{header|min}}==
<syntaxhighlight lang="min">null null? puts!</syntaxhighlight>
{{out}}
<pre>true</pre>
 
=={{header|Modula-3}}==
Line 2,101 ⟶ 2,201:
if {![dict exists $dic nullval]} ...</syntaxhighlight>
Note that lists do not support anything like nulls, since they are strictly sequences of values.
 
=={{header|TXR}}==
=={{trans|Common Lisp}}==
TXR Lisp has a <code>nil</code> symbol which serves as the empty list and Boolean false, like Common Lisp and similar dialects. It is a very important symbol which plays a central role.
 
Variable definitions, global and local, without initial value expressions take on the value <code>nil</code>. Elements of newly created vectors and structure slots are <code>nil</code> by default. Optional function parameters that don't receive arguments are given <code>nil</code> arguments by default. Many functions which search for something use <code>nil</code> for indicating not found.
 
Object-oriented programming in TXR Lisp is done with structures, which do not provide a CLOS-like object system. The <code>nil</code> object isn't a structure, and so it cannot take slot references, or method invocation. Only structures have methods, which means that it's not possible to define a null object method <code>m</code> such that <code>obj.(m)</code> can be invoked if <code>obj</code> is an expression evaluating to <code>nil</code>.
 
The Gang-of-Five Null Object Pattern can be employed: defining struct types that behave like null. This null object doesn't have to be related by inheritance to the structs in conjunction with which it is used.
 
<syntaxhighlight lang="txrlisp">
(defstruct null-widget ()
(:method popularity (me) 0))
 
(defvarl null-widget (new null-widget))
 
(defstruct real-widget ()
pop
(:method popularity (me) me.pop))</syntaxhighlight>
 
In situations when a null object would be used simply to provide safe treatment of null without the verbosity of checks for its presence, and a default value of <code>nil</code> is acceptable, TXR Lisp has null-safe slot and method access: <code>obj.?slot</code>, <code>obj.?(method arg)</code>.
 
The expression <code>w.?(popularity)</code> will evaluate to <code>nil</code> if <code>w</code> is <code>nil</code>, being equivalent to <code>(if w w.(popularity))</code>, except that <code>w</code> is evaluated only once.
 
Like in Common Lisp, <code>nil</code> an instance of the type <code>null</code>, which is a unit type having only that instance. And <code>nil</code> is also the name of the bottom type of the type system: the <code>nil</code> type is the subtype of every type, including itself.
 
Like in Common Lisp, the expression <code>(or a b c ...)</code> evaluates the arguments from left to right, returning the value of the leftmost one which does not evaluate to <code>nil</code>.
 
<syntaxhighlight lang="txrlisp">;; Find widget in one of three places in order
(defun find-widget (name)
(or [%widget-hash% name]
(lookup-local-widget name)
(lookup-global-widget name)))</syntaxhighlight>
 
=={{header|Ursa}}==
Line 2,170 ⟶ 2,304:
</syntaxhighlight>
 
=={{header|V (Vlang)}}==
V (Vlang) does not have nor normally allow null or nil (also called "the billion dollar mistake"):
 
1) All primitive types/variables have default values.
Line 2,178 ⟶ 2,312:
 
3) Usage of voidptr or nil, only done in unsafe, and is usually only for the purposes of interoperability with other languages.
<syntaxhighlight lang="v (vlang)">
// Null or nil not used, default values for various primitive types/variables instead:
 
Line 2,204 ⟶ 2,338:
 
It is always easy to test for nullness either by querying a variable's type or checking the value of a boolean expression involving a potentially null variable.
<syntaxhighlight lang="ecmascriptwren">// Declare a variable without giving it an explicit value.
var s
 
885

edits