Properly using Ruby's specialness

I was recently reading a presentation on “10 things Java programmers
should know about Ruby.” Like many similar discourses, it talked about
classes being objects and singleton methods etc. etc. Now, I am familiar
with these different things, but I think I am too stupid to discern
their inherent worth.

  1. Open classes. The other day, in a little Blackjack game I wrote in
    Ruby, I used this feature to add in a method to the Array class instead
    of making a class that inherited from Array and added that method.
    However, a) I’m not sure if that was the “right” way and b) I’m not sure
    if there is an advantage to that approach over the latter, per se.

  2. Singleton methods. I really can’t think of a particular example where
    I would use this… please help!

  3. Blocks. Although now (after some practice and getting used to) these
    make sense to me when I use them with methods already designed, I don’t
    think I have internalized them to the point where I would write my own
    methods that accepted them and worked with them. Has anyone else been in
    the same boat, or do they usually just “click”?

Thank you and sorry for the noobness,

J

On Jan 17, 2008, at 1:04 PM, J. Cooper wrote:

  1. Open classes. The other day, in a little Blackjack game I wrote in
    Ruby, I used this feature to add in a method to the Array class
    instead
    of making a class that inherited from Array and added that method.
    However, a) I’m not sure if that was the “right” way and b) I’m not
    sure
    if there is an advantage to that approach over the latter, per se.

Open classes are best used sparingly. There are problems with them,
of course, in that your code might collide with someone else’s code.
The plus though is that all instances of the changed class are
suddenly empowered with new methods you can count on. Some good uses,
in my opinion, are:

  • Conversion methods – I would rather type %w[a b c].to_csv than
    CSV.generate_line(%w[a b c]. I don’t feel there’s much danger of
    namespace collision here either due to the specific types in the
    method names. Some disagree and feel this is polluting the namespace
    though.
  • DSL – It can often be convenient to make Ruby understand the
    language of your problem rather than to express your problem in Ruby.
  1. Singleton methods. I really can’t think of a particular example
    where
    I would use this… please help!

Well, technically you use this feature in Ruby anytime you create a
class method. Outside of that, it’s another feature best used in
moderation. It does have interesting possibilities though. Here’s an
example to try and get you thinking in new directions:

def add_counts(array)
counts = array.inject(Hash.new(0)) { |c, e| c.merge(e => c[e] +

  1. }

class << array; self; end.send(:define_method, :counts) do
?> counts
end
end
=> nil
a = Array.new(10) { rand(6) }
=> [2, 3, 3, 3, 0, 2, 4, 3, 4, 3]
add_counts(a)
=> #Proc:0x0059dc60@:11(irb)
a.counts
=> {0=>1, 2=>2, 3=>5, 4=>2}

  1. Blocks. Although now (after some practice and getting used to)
    these
    make sense to me when I use them with methods already designed, I
    don’t
    think I have internalized them to the point where I would write my own
    methods that accepted them and worked with them. Has anyone else
    been in
    the same boat, or do they usually just “click”?

I wrote about this on my blog a while back. Maybe it will help:

http://blog.grayproductions.net/articles/code_as_a_data_type

James Edward G. II

James Edward G. II

J. Cooper wrote:

if there is an advantage to that approach over the latter, per se.
Thank you and sorry for the noobness,
It seems like you want to read the book “Design Patterns in Ruby”. It
goes into great detail when to use what, and why, and such stuff.

Best regards,

Jari W.

On Jan 17, 2008, at 2:04 PM, J. Cooper wrote:

of making a class that inherited from Array and added that method.
However, a) I’m not sure if that was the “right” way and b) I’m not
sure
if there is an advantage to that approach over the latter, per se.

That was the correct way to do it! The advantage is you can
instantiate an array object like normal ([]), instead of having to do
MyArray.new(3, 4, 5)

  1. Singleton methods. I really can’t think of a particular example
    where
    I would use this… please help!

When you would need to add a method into a class, or create a
subclass with a special method BUT the method is only used by one
object (IE, only one instantiation of MyArray).

Also, you should use it when you want methods to be called within a
class but outside of a method definition.

  1. Blocks. Although now (after some practice and getting used to)
    these
    make sense to me when I use them with methods already designed, I
    don’t
    think I have internalized them to the point where I would write my own
    methods that accepted them and worked with them. Has anyone else
    been in
    the same boat, or do they usually just “click”?

They typically just click :slight_smile:

On 1/17/08, James G. [email protected] wrote:

Open classes are best used sparingly. There are problems with them,
of course, in that your code might collide with someone else’s code.
The plus though is that all instances of the changed class are
suddenly empowered with new methods you can count on. Some good uses,
in my opinion, are:

  • Conversion methods
  • DSL

I think that rather than sparingly, the adverb should be carefully.

Open classes are very powerful in situations like building a
framework, (e.g. Rails). Features such as plugins, use formalized
patterns of extending open classes to allow opening classes while
minimizing the potential for collisions.

counts = array.inject(Hash.new(0)) { |c, e| c.merge(e => c[e] +

  1. }

class << array; self; end.send(:define_method, :counts) do
?> counts
end
end

Right, another is to accomplish what the OP did by adding an instance
to Array in a safer more controlled fashion. Rather than “duck
punching” all now and future instance of Array we can specialize
particular instances.

http://blog.grayproductions.net/articles/code_as_a_data_type


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hmm… yeah, I think I may literally be too dumb for Ruby. I guess I
just can’t get my head around the dynamicness. :frowning:

Thanks for the replies

On Jan 17, 2008, at 3:02 PM, Rick DeNatale wrote:

if there is an advantage to that approach over the latter, per se.

I think that rather than sparingly, the adverb should be carefully.

Open classes are very powerful in situations like building a
framework, (e.g. Rails). Features such as plugins, use formalized
patterns of extending open classes to allow opening classes while
minimizing the potential for collisions.

In an example in Practical Ruby Projects, the author has to load some
some operating specific code. He feels that open classes are great
for that. He codes up the general interface of the class and then
insert the other methods tailored to the operating system later.

This does seem to come out smoother than having to deal with a bunch
of specific subclasses. The unneeded code is just not added in.

James Edward G. II

On Jan 17, 2008 10:10 PM, James G. [email protected] wrote:

In an example in Practical Ruby Projects, the author has to load some
some operating specific code. He feels that open classes are great
for that. He codes up the general interface of the class and then
insert the other methods tailored to the operating system later.

This does seem to come out smoother than having to deal with a bunch
of specific subclasses. The unneeded code is just not added in.
There is almost no Ruby quiz solution I have ever submitted that does
not do that, it feels somehow like, look Ruby I know better than you
do though :wink:

James Edward G. II


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

My personal rule of thumb is, that when something “appears” logical and
straightforward, I use it.

And if i have had bad experience with it in the past, I dont use that
feature.
In the end I use only a subset of Ruby (but it makes me happy because it
is a lot more elegant than any other language I know of).