Ich benutze F # und weiß nicht viel von Scala, außer dass es oft einige Ähnlichkeiten zwischen diesen Sprachen gibt. Aber während ich die Implementierung von Akka Streams in Scala betrachtete, bemerkte ich die Verwendung von operator ~ & gt; so ist das in F # leider nicht möglich. Ich spreche nicht über Symbol "~", das nur in F # am Anfang von unären Operatoren verwendet werden kann, das ist nicht wichtig. Was mich beeindruckt hat, ist die Möglichkeit, solche Graphen zu definieren:
%Vor% Da verschiedene Diagrammelemente verschiedene Typen haben (Quelle, Fluss, Senke), ist es nicht möglich, einen einzelnen Operator in F # zu definieren, der über diese hinweg funktioniert. Aber ich frage mich, warum das in Scala möglich ist - weil Scala das Überladen der Methode unterstützt (und F # nicht)?
AKTUALISIEREN. Fydor Soikin zeigte mehrere Möglichkeiten der Überladung in F #, die verwendet werden könnten, um eine ähnliche Syntax bei der Verwendung von F # zu erreichen. Ich habe das hier und hier versucht, wie es aussehen könnte:
%Vor%Jetzt können wir den folgenden Code schreiben:
%Vor%Tatsächlich hat Scala mindestens vier verschiedene Möglichkeiten, damit es funktioniert.
(1) Überladen der Methode.
%Vor%(2) Vererbung.
%Vor%(3) Typklassen und ähnliche generische Konstrukte.
%Vor% (mit Streamable[Flow], Streamable[Sink], ...
Instanzen, die die benötigte Funktionalität bereitstellen).
(4) Implizite Conversions.
%Vor% (mit implicit def flowCanStream(f: Flow): Streamable = ???
, etc.).
Jeder von ihnen hat seine eigenen Stärken und Schwächen, und alle sind stark in verschiedenen Bibliotheken verwendet, obwohl der letzte etwas in Ungnade gefallen ist, weil es zu einfach ist, Überraschungen zu erzeugen. Aber um das von dir beschriebene Verhalten zu haben, würde jedes von diesen funktionieren.
In der Praxis ist es in Akka Streams tatsächlich eine Mischung aus 1-3 was ich sagen kann.
Erstens unterstützt F # vollständig das Überladen von Methoden:
%Vor%Dann können Sie das Überladen von Top-Level-Operatoren durch ein erstes Argument mit Hilfe von statisch aufgelösten Typ-Constraints und einigen cleveren syntaktischen Tricks erreichen:
%Vor%Und schließlich, wenn Sie auch das zweite Argument wirklich überladen wollen, können Sie das auch tun, indem Sie die Hilfe von überladenen Instanzmethoden nutzen:
%Vor% Der Nachteil (oder, man könnte argumentieren, die Oberseite) von all dem ist, dass alles zur Kompilierzeit passiert (siehe diese inline
s überall?). Wahre Typklassen wären definitiv besser, aber Sie können viel mit statischen Beschränkungen und Überladung tun.
Und natürlich können Sie auch in F # gute alte Vererbung machen:
%Vor%Aber ... Vererbung? Wirklich?
Das heißt, es ist selten die Mühe wert. In der Praxis können Sie das Endziel normalerweise über normale Funktionen erreichen, und vielleicht auch nur eine Auswahl von optional zu öffnenden benutzerdefinierten Operatoren, nur für zusätzlichen Komfort. Überladene Operatoren mögen zuerst wie ein glänzendes, cooles Spielzeug aussehen, aber sie sind gefährlich leicht zu übernutzen. Erinnere dich an C ++, lerne die Lektionen: -)
Tags und Links scala f# overloading