A Little Unnecessary Smalltalk Envy
In A Little Head Trauma…: Returning None is Evil, Mark Derricutt provoked a brief moment of Smalltalk envy.
(self doSomethingThatMightReturnNil) ifNotNil: [val | val doSomethingWithNoHassle].
In addition to what Mark was actually responding to, it is an annoyance that I’ve had repeatedly in Ruby but never really considered fixing. Until now.
The annoying code:
tmp = doSomethingThatMightReturnNil tmp.doSomethingWithNoHassle if tmp
Just look at those tmp variables.
This is the ‘cure’:
class Object def if_not_nil(&blk) yield(self) if blk end end class NilClass def if_not_nil(&blk) end end
I like monkey patching.
And now I can write:
doSomethingThatMightReturnNil.if_not_nil { | v | v.doSomethingWithNoHassle }
Which is so much nicer [UPDATE: and nicer still after Sean prompted me to actually get Mark's example right].
That really does look like Smalltalk, doesn’t it?
Not really.. because you’re passing the object to another function.. its easy enough to do a check inside doSomethingWithNoHassle on whether something is nil or not. Where Mark’s example highlights the beauty of the class heriarchy and yours does not (but could) is when you need to call a method ON the object.. so..
doSomethingThatMightReturnNil.if_not_nil { | v | v.render }
where calling v.render on nil would have caused a method not defined exception or whatever.
Sean
November 23, 2007 at 12:28 am
You’re right, I should be paying more attention. I didn’t translate Mark’s example properly. I’ll fix that. Thanks!
hutch
November 23, 2007 at 12:35 am
In Common Lisp:
(when-let (val (do-somethitg-that-might-return-nil))
(do-something-with-no-hassle val))
;)
Pascal Costanza
November 23, 2007 at 4:02 am
And if you’re willing to tolerate the anaphoric Common Lisp stuff:
which is completely untested by the way
[Note to you non CLers: (do-something-with-no-hassle val) is dispatching on val, and so is more similar to 'val.doSomethingWithNoHassle' than ' doSomethingWithNoHassle(v)']
[Note to you CLers: I'm always a little jealous of CL :-) I generally program in two languages these days: Ruby, CL -- but I miss Smalltalk, and APL for that matter]
hutch
November 23, 2007 at 9:02 am
Hello Bob. I just wrote a couple of tests on http://blog.teksol.info/2007/11/23/a-little-smalltalk-in-ruby-if_nil-and-if_not_nil
Shouldn’t that be a Gem ? Seems like a useful addition to Ruby. Maybe it could be added to Facets ?
Thanks for sharing !
Francois Beausoleil
November 23, 2007 at 9:04 am
Nice tests Francois. I’m going to have to start taking these little snippets seriously enough to write those tests myself.
Now, the only thing left is to work out how to do the ‘else’ part. Smalltalk and CL both provide that capability. I can’t think of a satisfying way to do that in Ruby.
hutch
November 23, 2007 at 9:30 am
This may not be even remotely elegant, but I did conjure this up for fun:
class ElseHandler
def otherwise(&blk)
blk.call
end
end
class Object
def otherwise(&blk)
self
end
end
Which should allow for:
doSomethingThatMightReturnNil.if_not_nil { | v | v.render }.otherwise { panic! }
Chris
November 23, 2007 at 2:45 pm
@Chris – You don’t even need to that with the original solution, assuming it returns self back. So you’d end up doing:
doSomethingThatMightReturnNill
.if_not_nil { | v | v.render )
.if_nil { panic! }
Mark Derricutt
November 26, 2007 at 6:53 am
Mark: that’s more or less what I was thinking of, but you loose the result which I think might be troublesome.
Chris: That’s a good idea, but I don’t think you need the ElseHandler. What about:
This isn’t 100%, might need to do otherwise_if_nil and otherwise_if_not_nil…
Francois: it seems that I’m still not doing unit tests. Sigh.
hutch
November 26, 2007 at 8:39 am
Shouldn’t that be if_nil? and unless_nil?
Brian Demant
November 26, 2007 at 9:31 am
Isn’t the ‘?’ usually used with predicates (i.e. methods that return true or false)? Maybe I’m confusing my languages here? :-)
I understand where you’re coming from with the ‘unless’ suggestion, and it is kind of attractive, but maybe it’s a little too close to a double negative? It’d be nice to have a word that meant ‘not nil’. Kind of like if_something and if_nothing — not sure I like that either.
hutch
November 26, 2007 at 10:10 am
http://pastie.caboo.se/122398 shows how to achieve following behavior:
p 1.nonil + 2 + 10
=> 13
p nil.nonil + 3 + 10
=> #
No need for blocks if we can just swallow following messages.
Might not be the best way, but yet another one :)
manveru
November 26, 2007 at 9:36 pm
Aha – I thought of a similar (read: identical) way of doing it – http://howto.blog.bagofscum.com/2008/09/ifnotnil.html
Asfand Yar Qazi
October 23, 2008 at 10:59 am