为什么sqrt()不是Numeric的方法?

Kap*_*old 28 ruby oop

在Ruby中,一切都是对象.这就是为什么我不明白为什么我们有数学模块.在我看来,Math模块中的大多数(全部?)函数应该是Integer,Float等数值类型的方法.

而不是

Math.sqrt(5)
Run Code Online (Sandbox Code Playgroud)

拥有它会更有意义

5.sqrt
Run Code Online (Sandbox Code Playgroud)

这同样适用于sin,cos,tan,log10等等.

有谁知道为什么所有这些函数最终都出现在Math模块中?

Mic*_*son 23

我不知道Ruby的早期历史,但我感觉Math模块是在C <math.h>标题之后建模的.不过,这是Ruby标准库中的一个奇怪的东西.

但是,这是Ruby!所以你总是可以淘汰猴子补丁!

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
Run Code Online (Sandbox Code Playgroud)


Mar*_*off 9

为了扩展迈克尔的答案,没有必要手动定义所有这些方法.请注意,我明确跳过了两个带有两个参数的Math方法.

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
Run Code Online (Sandbox Code Playgroud)

输出:

5.0
2.0 
Run Code Online (Sandbox Code Playgroud)

至于为什么这些方法已经不包括在内Numeric,我真的不确定一个很好的理由.我不认为安德鲁提到的命名空间污染在Numeric课堂上特别危险; 迈克尔可能正处于历史遗留问题的正确轨道上.

  • 将其更改为`define_method(method)do |*args | Math.send(方法,自我,*args)结束,并且不再需要排除`hypot`或`ldexp`. (9认同)
  • 表达式(Math.methods - Module.methods)也可以缩短为Math.methods(false) (3认同)

Ste*_*set 7

我已经重写马克的回答更加简洁,并且不需要去除hypotldexp,因为我用这种方法我自己.

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
Run Code Online (Sandbox Code Playgroud)