-
Notifications
You must be signed in to change notification settings - Fork 108
Null, Nil, and UnityEngine.Object
In addition to Clojure's built-in nil?
function, Arcadia introduces arcadia.core/null?
and arcadia.core/null->nil
. These require some explanation beyond their docstrings.
C# supports operator overloading, the ability to modify the behavior of operators such as ==
depending on the static types of the arguments. Crucially, this overload is early bound: it will only take effect if the overloaded types of the arguments are statically known. That is, the expression
x == y
may well evaluate to a different value depending on how x
and y
are type annotated, even for the same runtime values of x
and y
. In other words, it is an inherently static feature of C#, which presents some awkwardness for a dynamic language like Clojure.
Unity uses operator overloading to emulate the behavior of null
for destroyed UnityEngine.Object
instances. Say x
is, in fact, a GameObject
instance (a subclass of UnityEngine.Object
):
GameObject x = new GameObject();
If x has not been destroyed, the following will evaluate to false
, and if it has been destroyed, to true
:
x == null
However, the following will evaluate to false
regardless of whether x
has been destroyed or not:
(System.Object x) == null
This behavior and its drawbacks are described in more detail here. According to the same blog post,
...if we were building our API from scratch, we would have chosen not to do a custom null check, but instead have a myObject.destroyed property you can use to check if the object is dead or not
Unfortunately, we seem to be stuck with this behavior.
nil
is a very important value in Clojure. Clojure does not respect Unity's "fake" null behavior. For any runtime value x
that is, in fact, a UnityEngine.Object, rather than nil
, the Clojure code
(nil? x)
will evaluate to false
.
Arcadia introduces arcadia.core/null?
and arcadia.core/null->nil
to bridge these two systems.