2010-05-16 11 views
19

En Ruby todo es un objeto. Es por eso que no entiendo por qué tenemos el módulo de Matemáticas. Me parece que la mayoría (¿todas?) De las funciones en el módulo Math deberían haber sido métodos en los tipos numéricos como Integer, Float, etc.¿Por qué sqrt() no es un método en Numérico?

E.g. en lugar de

Math.sqrt(5) 

que tendría más sentido tener

5.sqrt 

Lo mismo ocurre con sin, cos, tan, log10 y así sucesivamente.

¿Alguien sabe por qué todas estas funciones terminaron en el módulo de Matemáticas?

+0

'5.sqrt' es tooo MUUCHO hacia atrás – Anycorn

+0

Kaptajn, debido a que es demasiado oop OMI, y es muy raro para los programadores que migran desde otros idiomas – horseyguy

+0

#abs es un método sin embargo: -6.abs # => 6 – horseyguy

Respuesta

18

No conozco la historia temprana de Ruby, pero tengo la sensación de que el módulo Math se modeló después del encabezado C <math.h>. Sin embargo, es un pato extraño en la biblioteca estándar de Ruby.

Pero, ¡es Ruby! ¡Así que siempre puedes sacar el parche del mono!

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 
3

Cuando se habla de módulos y espacios de nombres, programación Ruby (el pico) dio un ejemplo de un objeto con ambas funciones matemáticas mezcladas, y las funciones que ver con la moralidad mezclado, de modo que pudiera calcular how many angels can dance on the head of a pin. Luego señaló que sin un espacio de nombres adecuado, sin podría ser un término ambiguo.

Así que tal vez se trate de contaminación del espacio de nombres.

+0

Esa preocupación se aplica a la tipificación de pato en general, no solo a las funciones matemáticas. Dudo que esa sea la razón. – KaptajnKold

6

Para ampliar Michael's answer, no hay necesidad de definir todos esos métodos a mano. Tenga en cuenta que omito explícitamente los dos métodos matemáticos que toman dos argumentos.

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 

Salida:

5.0 
2.0 

En lo que respecta a exactamente por qué estos métodos no están incluidos en Numeric ya, realmente no estoy seguro de una buena razón. No creo que la contaminación del espacio de nombre como Andrew mentioned sea particularmente un riesgo en la clase Numeric; Michael probablemente esté en el camino correcto con un histórico arrastre.

+7

Cambie eso a 'define_method (método) do | * args | Mates.send (method, self, * args) end', y ya no es necesario excluir 'hypot' o' ldexp'. – molf

+3

La expresión (Math.methods - Module.methods) también puede ser acortado a simplemente Math.methods (falso) –

+0

combinado para mayor comodidad en una sola línea (en la clase numérico): 'Math.methods .Cada (false) {| m | define_method m do | * args | Math.send m, self, * args end} ' –

5

He reescrito la respuesta de Mark para ser más conciso, y no es necesario eliminar hypot y ldexp, ya que estoy usando este enfoque yo mismo.

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 
0

5 ** 0.5 demuestra que el operador de exponenciación de rubí puede manejar raíces cuadradas directamente, como para registro, el pecado, etc., éstos tienen más sentido para mí como funciones globales en lugar de métodos: sus orígenes se encuentran en las matemáticas y no están estrechamente relacionados con cualquier instancia de flotación.

Cuestiones relacionadas