Ich verwende die Azavea Numeric Scala-Bibliothek für allgemeine mathematische Operationen. Allerdings kann ich diese nicht mit der Scala Collections API verwenden, da sie eine scala Numeric erfordern und es so aussieht, als ob die beiden Numerics sich gegenseitig ausschließen. Gibt es eine Möglichkeit, wie ich vermeiden kann, alle mathematischen Operationen auf Scala Collections für Azavea Numeric neu zu implementieren, abgesehen davon, dass alle Typen Kontextgrenzen für beide Numerics haben müssen?
%Vor%Wo Azavea Numerisch als
definiert ist %Vor% Die allgemeinste Lösung wäre, eine Klasse zu schreiben, die com.azavea.math.Numeric
umschließt und scala.math.Numeric
darin implementiert:
Implementiere dann eine implizite Konvertierung:
%Vor% Die Tatsache, dass n
selbst implizit ist, ist hier der Schlüssel: Es erlaubt, dass implizite Werte des Typs com.azavea.math.Numeric
automatisch verwendet werden, wenn ein impliziter Wert von
type scala.math.Numeric
wird erwartet.
Beachten Sie, dass Sie wahrscheinlich auch den umgekehrten Fall ausführen möchten (schreiben Sie eine Klasse namens ScalaNumericWrapper, die com.azavea.math.Numeric im Sinne von scala.math.Numeric implementiert).
Nun gibt es einen Nachteil für die obige Lösung: Sie erhalten eine Umwandlung (und damit eine Instanziierung) bei jedem Aufruf (zu einer Methode, die eine Kontextbindung vom Typ scala.math.Numeric
hat, und wo Sie nur eine Instanz von com.azavea.math.Numeric
ist im Umfang).
Sie werden also eigentlich eine implizite Singleton-Instanz von AzaveaNumericWrapper für jeden Ihrer numerischen Typen definieren wollen. Angenommen, Sie haben die Typen MyType
und MyOtherType
, für die Sie Instanzen von com.azavea.math.Numeric
definiert haben:
Denken Sie auch daran, dass der offenkundige Hauptzweck der Numeric-Klasse von azavea darin besteht, die Ausführungsgeschwindigkeit erheblich zu verbessern (hauptsächlich aufgrund der Typ-Parameter-Spezialisierung).
Wenn Sie den Wrapper wie oben verwenden, verlieren Sie die Spezialisierung und damit die Geschwindigkeit, die daraus entsteht. Spezialisierung muss den ganzen Weg hinunter verwendet werden,
und sobald Sie eine generische Methode aufrufen, die nicht spezialisiert ist, treten Sie in die Welt der unspezialisierten Generika ein (selbst wenn diese Methode dann eine spezialisierte Methode zurückruft).
Wenn es auf die Geschwindigkeit ankommt, versuchen Sie, Azavas Numeric
direkt anstelle von scalas Numeric
zu verwenden (nur weil AzaveaNumericWrapper es intern verwendet)
bedeutet nicht, dass Sie eine Geschwindigkeitssteigerung bekommen, da Spezialisierung hier nicht stattfindet).
Sie haben vielleicht bemerkt, dass ich in meinen Beispielen vermieden habe, Instanzen von AzaveaNumericWrapper
für die Typen Int
, Long
und so weiter zu definieren.
Dies liegt daran, dass für diese Typen bereits (in der Standardbibliothek) implizite Werte von scala.math.Numeric vorhanden sind.
Sie könnten versucht sein, sie einfach zu verstecken (über etwas wie import scala.math.Numeric.{ShortIsIntegral => _}
), um sicherzugehen, dass Ihre eigene (azavea-unterstützte) Version verwendet wird,
aber das hat keinen Sinn. Der einzige Grund, den ich mir vorstellen kann, wäre, es schneller laufen zu lassen, aber wie oben erklärt, wird es nicht funktionieren.
Sie können die gute Lösung von Régis Jean-Gilles verwenden und Azavea's Numeric einpacken. Sie können auch versuchen, die Methoden selbst zu erstellen, aber mit Azavea's Numeric. Abgesehen von NumericRange sollten die meisten ziemlich einfach zu implementieren sein.
Sie könnten sich jedoch für Spire interessieren, was auf Azaveas Numeric-Bibliothek zurückzuführen ist. Es hat alle dieselben Funktionen, aber auch einige neue (mehr Operationen, neue Nummerntypen, Sortierung und Auswahl usw.). Wenn Sie 2.10 verwenden (der Großteil unserer Arbeit ist auf 2.10 ausgerichtet), eliminiert die Verwendung von Numeric von Spire praktisch den gesamten Overhead eines generischen Ansatzes und läuft oft so schnell wie eine direkte (nicht-generische) Implementierung.
Das heißt, ich denke, Ihre Frage ist ein guter Vorschlag; Wir sollten wirklich eine toScalaNumeric
-Methode für Numeric hinzufügen. Welche Scala-Sammelmethoden haben Sie geplant? Spire fügt Arrays mehrere neue Methoden hinzu, z. B. qsum, qproduct, qnorm (p), qsort, qselect (k) usw.