The .andand hack is at least arguable, inasmuch as it adds behavior to nil itself that is at least applicable to nil, rather than "quacking" or anything else that has nothing to do with nil.
You are also begging to create a fragile, magical system that will randomly throw errors and die in strange places that seem to have nothing to do with the error itself or can't possibly happen. I speak from experience. Do not hide the fact you got a null when you didn't expect. Basically, your program is still going to crash, it's only a matter of when it goes and how much data it corrupts before it happens. You want it to die sooner, before it scrambles anything more. (Again, using "andand" is different as it shows that you were explicitly concerned about getting a null back and are doing what it takes to get the null out of the system; it's just refactored "if null then X else Y" which is fine.)
Suggesting that you rewrite nil for the purpose of hiding errors is an incredible immature thing to do; I'm sorry to have to call it out but given what it could do to people and how much of their lives could be wasted by following this suggestion it needs to be said strongly:
Do Not Do This.
(If Ruby could add scoped monkeypatching, the equation radically changes from "Do Not Do This" to "jerf is uncomfortable with this style but has no particular objections otherwise", which is a completely different thing; then I'd be expressing an opinion on style instead of warning you that you're going to create a nightmare system if you do that.)
(And yeah, I said null, not nil; that's because this applies to more than just Ruby and I wanted to keep it generic.)
My favorite is the andand gem: http://github.com/raganwald/andand/tree/master
It lets you turn code like this..
entry.at('description') && entry.at('description').inner_text
..into code like this.. entry.at('description').andand.inner_text begin entry.at('description').index_text
rescue NoMethodError; end
? begin
entry.at('description').indx_txt
rescue NoMethodError
end
? With the generic rescue you will always get nil back. With #andand you get nil from nil and a NoMethodError from objects, which is usually what you want.Also, if #index_text is correctly spelled but it raises a NoMethodError, you're silently discarding it again. For this reason, I avoid silently discarding exceptions even when I think I know what I'm doing. If I'm wrong, I'm in a lot of trouble...
It's also pretty dangerous if you don't have a very good test coverage (and good tests), because it hides potential bugs. And it can break code which relies on the default behavior of `nil` (or other built-in objects).
That's one of the biggest issues I have with monkey patching of builtin classes in Ruby or Smalltalk: it's not scoped/namespaced.
edit: by comparison, Haskell's operators redefinition is scoped, so though you can redefine `+` as `-`:
Prelude> let (+) = (-) in print (3+5)
-2
this redefinition will only span your module and won't affect third-party library (unless you export the change and they import it for course).In Smalltalk, the right thing to do is use a subclass. Have that function return an instance of a subclass of UndefinedObject that's tailored to the context. Instead of returning nil, return a NotApplicable instance. Then you can have it print out a locale appropriate 'n/a' message when you need to display the value.
I never knew this but it will definitely come in handy.