Thursday, November 08, 2007

Ruby Quickies

1)  Whenever you've got a method that returns an array, there's a design question of what to do on no results.  Do you return a zero element array, or nil?  Your code that processes the results will be cleaner if you can always assume an array will come back (that way saying things like "Foreach x in results {...}" will simply fall through if results is empty).  But does that mean that you have to do some ugly conditionalizing inside the method to check for nil and create an empty array?

In Ruby you've got the lovely "to_a" object method.  Run it on an array, you get back the array.  Run it on a single element, you get back [element].  And, best of all?  Run it on nil, and you get back [].  Exactly what you want.

 

2) This is actually a trick that dates back to Smalltalk, but Ruby can do it to so Ruby is cool.  I have a string in my UI, and what I would really like to do, for fun, is replace that with a random choice from N strings.  So instead of just returning "Are you sure?" for instance I might return "Really?" or "Do you want to think about that?" and the like.

Problem - Ruby's array class has no random method.

Solution -  Stick this someplace in your code:

class Array

 def self.random

   self[rand(self.length)]

 end

end

 

And now it does.  Congratulations, you've just extended a system class.  Now you can do this:

["Are you sure?", "Really?", "Do you want to think about that?"].random

and get back a different result each time.

 

 

Technorati tags:

3 comments:

jason said...

for a random item in an array, why not just do:

my_array[rand(my_array.size)]

Duane said...

Well, that's exactly what the override does. The way you suggest works fine if your array is in a variable, but if you're doing something on the fly like in my example you wouldn't want to write out

["a", "b", "c"][rand(["a","b","c"].size]

now would you? Sure, I could put my constants into a variable, but part of the beauty is in not being forced to do that.

Ramon Leon said...

Because

my_array[rand(my_array.size)]

is ugly and stinks of procedural code and shows the implementation.

It should be done by sending a clear simple message to an object instead.

my_array.random

is the proper object oriented way to do this, and yes, this is how Smalltalk does it.