Nothing is an object
Yes, I jest, but the point is that Ruby takes the idea of "everything is an object" to a level where even "nothing" (i.e. nil) is an object:
nil.class
# => NilClass
Not only does this showcase the consistency of Ruby's object model, but it can also be quite useful in practice, such as when invoking to_s or to_i to ensure we get a string or integer representation of a potential nil value:
inconsistent_data = [
{ name: "Alice", surname: "Smith", age: 30 },
{ name: "Bob", surname: nil, age: 5 },
{ name: "Charlie", surname: "Johnson", age: nil }
]
french_names = inconsistent_data.map do |data|
"#{data[:name]} #{data[:surname].to_s.upcase}".strip
end
# => ["Alice SMITH", "Bob", "Charlie JOHNSON"]
confirmed_adults = inconsistent_data.select do |data|
data[:age].to_i >= 18
end
# => [{ name: "Alice", surname: "Smith", age: 30 }]
const inconsistentData = [
{ name: "Alice", surname: "Smith", age: 30 },
{ name: "Bob", surname: null, age: 5 },
{ name: "Charlie", surname: "Johnson", age: null },
];
const frenchNames = inconsistentData.map((data) => {
const surname = data.surname ? data.surname.toUpperCase() : "";
return `${data.name} ${surname}`.trim();
});
// => ["Alice SMITH", "Bob", "Charlie JOHNSON"]
const confirmedAdults = inconsistentData.filter((data) => {
const age = typeof data.age === "number" ? data.age : 0;
return age >= 18;
});
// => [{ name: "Alice", surname: "Smith", age: 30 }]
History (nil vs null)
Most mainstream languages inherited null from the world of pointers and references. Tony Hoare introduced the idea of the "null reference" for ALGOL W in 1965, and that terminology spread far and wide through C-family languages, databases, and eventually JavaScript. null therefore carries a fairly low-level flavor: it sounds like a reference that points nowhere.
Ruby comes from a different branch of the family tree. Matz has been very explicit that Ruby was shaped by both Lisp and Smalltalk, and both of those languages already used nil. Lisp had NIL long before Ruby, and Smalltalk treated nil as an actual object.
That distinction matters because Ruby's nil is not just an empty hole in memory. It is the singleton instance of NilClass, which means it fully participates in Ruby's "everything is an object" model.