开发者

Why is sqrt() not a method on Numeric?

In Ruby everything is an object. That's why I don't understand why we have the Math module. It seems to me that most (all?) of 开发者_运维技巧the functions in the Math module should have been methods on the numeric types like Integer, Float and so on.

E.g. instead of

Math.sqrt(5)

it would make more sense to have

5.sqrt

The same goes for sin, cos, tan, log10 and so on.

Does anyone know why all these functions ended up in the Math module?


I don't know the early history of Ruby, but I have a feeling the Math module was modelled after the C <math.h> header. It is an odd duck in the Ruby standard library though.

But, it's Ruby! So you can always bust out the monkey patching!

class Float
  def sqrt; Math.sqrt(self); end
  def sin; Math.sin(self); end
  def cos; Math.cos(self); end
  def tan; Math.tan(self); end
  def log10; Math.log10(self); end
end


To expand on Michael's answer, there's no need to define all those methods by hand. Note that I explicitly skip the two Math methods that take two arguments.

class Numeric
  (Math.methods - Module.methods - ["hypot", "ldexp"]).each do |method|
    define_method method do
      Math.send method, self
    end
  end
end

puts 25.sqrt
puts 100.log10

Output:

5.0
2.0 

In regards to exactly why those methods are not included in Numeric already, I'm really not sure of a good reason. I don't think namespace pollution as Andrew mentioned is particularly a risk in the Numeric class; Michael is probably on the right track with historic carryover.


I've rewritten Mark's answer to be more concise, and not require removing hypot and ldexp, since I'm using this approach myself.

class Numeric
  Math.methods(false).each do |method|
    define_method method do |*args|
      Math.send(method, self, *args)
    end
  end
end

>> 3.hypot(4)
=> 5.0

>> Math::PI.sqrt
=> 1.7724538509055159

>> 10.log10
=> 1


When talking about modules and namespaces, Programming Ruby (the pickaxe) gave an example of an object with both mathematical functions mixed in, and functions to do with morality mixed in, so that it could calculate how many angels can dance on the head of a pin. It then noted that without proper namespacing, sin could be an ambiguous term.

So maybe it's about namespace pollution.


5 ** 0.5 demonstrates that ruby's exponentiation operator can handle square roots directly, as for log, sin etc, these make more sense to me as global functions rather than methods: their origins are in mathematics and are not closely related to any one float instance.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜