Liam (heptadecagram) wrote in ruby_lang,

Module or Class?

I haven't been programming in ruby for very long, less than a year. Something that I noticed today is that I'm unsure whether I'm declaring methods in "Ruby Way".

I needed to find the modes in an Array of data. Very straightforward (but feel free to critique the code itself in addition to my actual question):

  def mode(array)
    stats =
    array.each { |item| stats[item] += 1 } { |item, times| times == stats.values.max }.map {|k| k[0] }

"But wait," I thought. "This can be useful for more things than Arrays. Why not make it a method of the Enumerable module?"

module Enumerable
  def mode
    stats =
    self.each { |item| stats[item] += 1 } { |item, times| times == stats.values.max }.map {|k| k[0] }

I then went on to write all the statistical methods I needed into the Enumerable class. This made sense to me, since I write ruby code in a very functional style, and I wanted to be able to say { |n| n**2 }.select { |n| n > 10 }.median, or something similar. But then I remembered that the Math library does not work similarly: I call sqrt(value), as opposed to value.sqrt. It seems to me like putting the methods in the class or mixin makes much more sense: they can be overloaded more easily, so if I introduce quaternions, I don't have to redefine Math.sqrt, I just need to clarify Quaternion#sqrt. I also don't have to worry about getting strange inputs to the methods; it'll be the type I want (poor man's strong typing of methods, so to speak).

What is the Ruby Way or insight in doing these sorts of things? The Math library seems to take a namespace approach, but it feels so right (and so easy) to just extend the types I'm working with.

Also, why doesn't the Enumerable mixin have a size method? I couldn't find any derived (is that the correct term for a mixin?) classes that didn't have one (except Range), and it'd be nice to have a guaranteed way of getting the size or length of any Enumerable class.

  • Post a new comment


    default userpic