A kind-of universal “truth” that one becomes accustomed to as a programmer is that null aka NULL aka None means “nothing”:
#include <stdio.h> void main(int na, char** args) { printf("The value of NULL: %p\n", NULL); }
$ cc test.c && ./a.out The value of NULL: (nil)
$ csharp Mono C# Shell, type "help;" for help Enter statements below. csharp> Console.WriteLine("Null is: " + null); Null is: csharp>
$ python -c 'print "None is: " + str(None)' None is: None
Also, one has come to accept that null/NULL/None is “type-less”, i.e., is something unique, and certainly not classed with ordinary objects.
csharp> typeof(string); System.String csharp> typeof(null); (1,12): error CS1031: Type expected
Python>>> type("astring"); <type 'str'> Python>>> type(None); <type 'NoneType'>
OK, so Python seems to think that None has a type, which means that None is an instance of NoneType; let's confirm that:
>>> t = None.__class__ >>> isinstance(None, t); True >>> dir(None) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] >>> None.__repr__() 'None' >>> None.__hash__() 597501
Therefore, in Python, None is an object with a type. As it so happens, there is only one instance of NoneType which is none other than ... None.
Now, I can only assume therefore that None is a singleton, and will always have the same hash. Let's see if the implementation of Python on my Raspberry Pi comes out with the same value (I would expect it to):
[piedpiper:/home/pi] $ python Python 2.7.9 (default, Sep 17 2016, 20:26:04) [GCC 4.9.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> None.__hash__() 1073928066
Nope - seems the hash of None is something that is not universal—at least it's the same across invocations of the interpreter.
Ruby OTOH, has some noteworthy, slightly “off the beaten track” qualities to it's own version of ... nothing, that is: nil. I was going to pull a rabbit out of the hat and surprise you with it being an object, with a type, but Python ruined that party.
As it so happens though, Ruby's nil does have some features that make it interesting, and arguably enhance its status beyond the mundanity of C, C# and Python's equivalents:
On my x64-based Ruby implementation:
$ cat /etc/issue Ubuntu 14.04.5 LTS \n \l $ irb irb(main):001:0> nil.object_id => 4
4? How does the object ID (essentially the “key” for objects in Ruby) end up being 4? Is this universal? Let's try the version on my Raspberry Pi:
$ cat /etc/issue Raspbian GNU/Linux 8 \n \l $ irb irb(main):003:0> nil.object_id => 4
So it turns out that there's an interesting trick that gets used under the hood with certain values in Ruby. It's a bit long-winded (but interesting in an “under-the-hood-gems” kind of way), suffice to say that for certain simple values, notably true, false, nil and Fixnum's, the object_id is always the same across implementations:
irb(main):001:0> true.object_id => 2 irb(main):002:0> false.object_id => 0 irb(main):003:0> nil.object_id => 4 irb(main):004:0> 0.object_id => 1
Comments !