2010-05-16 7 views
19

In Ruby ist alles ein Objekt. Deshalb verstehe ich nicht, warum wir das Mathematikmodul haben. Es scheint mir, dass die meisten (alle?) Der Funktionen im Math-Modul Methoden für die numerischen Typen wie Integer, Float usw. sein sollten.Warum ist sqrt() keine Methode auf Numerisch?

z. statt

Math.sqrt(5) 

würde es mehr Sinn

5.sqrt 

Das gleiche gilt für sin, cos, tan, log10 und so weiter geht zu haben zu machen.

Weiß jemand, warum all diese Funktionen im Math-Modul gelandet sind?

+0

'5.sqrt' ist waaay tooo rückwärts – Anycorn

+0

Kaptajn, weil das zu IMO OOP ist, und ist zu seltsam für Programmierer aus anderen Sprachen Migration – horseyguy

+0

#abs ein Verfahren allerdings ist: -6.abs # => 6 – horseyguy

Antwort

18

Ich kenne nicht die frühe Geschichte von Ruby, aber ich habe das Gefühl, das Math-Modul wurde nach dem C <math.h> Header modelliert. Es ist eine seltsame Ente in der Ruby-Standardbibliothek.

Aber es ist Ruby! So können Sie immer die Affe flicken!

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

Wenn man über Module und Namensräume im Gespräch, Programmierung in Ruby (die pickaxe) gab ein Beispiel eines Objekts mit beiden mathematischen Funktionen mischt und Funktionen mit Moral zu tun mischt, so dass es how many angels can dance on the head of a pin berechnen konnte. Es stellte dann fest, dass ohne richtigen Namespacing sin ein mehrdeutiger Begriff sein könnte.

Also vielleicht geht es um Namespace Verschmutzung.

+0

Diese Sorge gilt im Allgemeinen für die Eingabe von Enten, nicht nur für die Math-Funktionen. Ich bezweifle, dass das der Grund sein könnte. – KaptajnKold

6

Um auf Michael's answer zu erweitern, müssen Sie diese Methoden nicht manuell definieren. Beachten Sie, dass ich die zwei Mathemethoden, die zwei Argumente verwenden, explizit überspringe.

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 

Ausgang:

5.0 
2.0 

In Bezug auf genau, warum sind diese Methoden nicht bereits in Numeric enthalten, ich bin wirklich nicht sicher einen guten Grund. Ich glaube nicht, Namensraum Verschmutzung wie Andrew mentioned ist besonders ein Risiko in der Numeric Klasse; Michael ist wahrscheinlich mit historischen Verschleppungen auf dem richtigen Weg.

+7

Ändere das zu 'define_method (method) do | * args | Mathematik.send (method, self, * args) end ', und es besteht keine Notwendigkeit mehr, "hypot" oder "ldexp" auszuschließen. – molf

+3

Der Ausdruck (Math.methods - Module.methods) kann auch abgekürzt werden nur Math.methods (false) –

+0

Kombiniert für die Bequemlichkeit in einen Einzeiler (in der Klasse Numeric): 'Math.methods (false) .each {| m | define_method m do | * Argumente | Math.send m, selbst, * args end} ' –

5

Ich habe Marks Antwort umformuliert, um präziser zu sein, und muss nicht hypot und ldexp entfernen, da ich diesen Ansatz selbst benutze.

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 zeigt, dass Rubys Potenzierungsoperator direkt Quadratwurzeln verarbeiten kann, wie für log, sin usw., diese mehr Sinn für mich als globale Funktionen anstatt Methoden: ihre Ursprünge sind in der Mathematik und sind nicht eng mit irgendeine Floatinstanz.