The most useful Monkeypatch ever March 8, 2008
In Java we all dread the dreaded NullPointerException of dread.
In Ruby nil is a class and we can do something about it.
Monkeypatching core classes is of course a Bad Thing(tm) but this particular one should* break nothing since we’re adding a self contained method to a class that doesn’t alter the functioning of any of the other methods on the class. Furthermore we’re adding something that simply makes sense, so when you call it sensible things happen. Now, as with most innovative thoughts, it isn’t. According to _why it’s been brought up by far more knowledgeable Ruby geeks than I: Jim Mernard, Dave Thomas, and Dan Fitzpatrick have all argued for this. Others have argued against. The others all work for The Man and are just trying to put you down.
Behold, the glory of nil.empty?
class NillClass
def empty?
return true
end
end
Oooh ahh… Bow before its glory! Bow I say!
Do you not see? NilClass is the void. It is nothingness incarnate. You may debate if it is really false, since how can nothing be true or false, but it is most assuredly empty, for how could nothingness ever contain something? Now you never need to @#$% check if a thing exists or not before checking if it’s empty.
More lately people including _why have been arguing for nil.blank? This is, of course, craziness. While I encourage such insanity in _why (it’s what makes him great) it is impossible. Nothing can not be blank, for it has no form, no surface, and only things can be blank. Nothing is neither blank, nor non-blank.** Rails has, of course, incorporated nil.blank? because they’d monkeypatch their grandmothers if they could figure out how. Personally, while I love this particular monkeypatch I don’t think any core classes should ever be monkeyatched in a distributed library or app, but YOUR app, that other apps don’t use as a foundation…. monkeypatch whatever-the-hell you want, just be sure to document it well.
*I say “should break nothing” but there is, of course, being stupid and using the unexpected, and slow, thrown exception to change the flow instead of checking for nil.
** Yes, the antonym for blank is “full”, but if you ask me, that makes no sense.
P.S. It’s a really good thing that Java isn’t monkeypatchable because if it was java.util.Calendar would be monkepatched a new and incompatible way in every single library out there because we all hate its @#$% guts. Use Joda Time instead.
Popularity: 4% [?]
This argument is less than sound. You’re arguing based on English definitions, not code definitions. But even so, `nil` is not _empty_, `nil` is _emptiness_.
Here’s some more counterpoint:
A `NULL` field in SQL doesn’t connote a void, but rather a _blank_, undefined state. `nil.blank?` makes sense and is defined by Rails because those fields can be `NULL` or empty strings, but usually connote the same thing. `@user.name.blank?` makes sense (and should return `true` if `nil` _or_ `”"`), `@user.name.empty?` does not.
Save `empty?` for things that can be empty: Arrays and Hashes, `[]` and `{}`. Certain methods should return arrays or hashes, empty or “full”, and if it’s returning `nil`, that’s a problem that should fail out when `empty?` is called on the object.
Yeah, I was contemplating the SQL issue when I wrote this *BUT* I don’t see this as a problem because in Ruby null really does connote a void. The problem, as I see it, is that SQL has 3 states populated, empty, and null but ActiveRecord isn’t returning you an object that accurately represents that. It’ll return you the thing or null. .blank? may make sense in Rails, but AFAIK it still doesn’t address the issue of things being nil. And, while you do need a difference between NULL and blank when querying, for almost all practical purposes they’re the same once you’ve gotten your results.
As far as basing it on English definitions. Yes, I am, because Ruby is written in English and uses English words to name its pieces. As far as nil being “emptyness” not “empty”, how can emptyness NOT be empty?
Emptiness == empty is a tautological argument, but I believe with some flaws. Emptiness is contained. A container can be empty. E.g.,
nil.to_s == “”
“”.empty? # => true
nil.to_a == []
[].empty? # => true
Hash.new(nil) == {}
{}.empty? # => true
Nil is being _contained_ by something in each case: a string, an array, a hash. The string, array, and hash are all empty. Nil is that emptiness. Nil itself is not empty because it cannot contain anything to begin with. Do you understand? The English definitions for “empty” and “emptiness” are different.