OCaml

Ocaml
OCaml Logo.svg
Paradigma Multi-Paradigma: funktional, Imperativ, modular,[1] objektorientierter
Familie Ml
Entworfen von Xavier Leroy, Jérôme Vouillon, Damien DoligezDidier Rémy, Ascánder Suárez
Entwickler INRIA
Erstmals erschienen 1996; Vor 26 Jahren
Stabile Version
4.14.0[2] Edit this on Wikidata / 28. März 2022; vor 4 Monaten
Disziplin tippen Gefolgert, statisch, stark, strukturell
Implementierungssprache Ocaml, C
Plattform IA-32, x86-64, Leistung, Sparc, Arm 32-64
OS Plattformübergreifend: Unix, Mac OS, Fenster
Lizenz LGPLV2.1
Dateiname -Erweiterungen .ml, .mli
Webseite ocaml.org
Beeinflusst von
C, Caml, Modula-3, Pascal, Standard ml
Beeinflusst
ATS, Coq, Ulme, F#, F*, Haxe, Opa, Rost, Scala
  • Objektives CAML bei Wikibooks

Ocaml (/ˈkæməl/ oh-Kam-əlfrüher Objektives CAML) ist ein allgemeiner Zweck, Multi-Paradigm-Programmiersprache das erweitert die Caml Dialekt von Ml mit objektorientierter Merkmale. OCAML wurde 1996 von geschaffen Xavier Leroy, Jérôme Vouillon, Damien DoligezDidier Rémy, Ascánder Suárez und andere.

Der ocaml Toolchain Beinhaltet eine interaktive obere Ebene Dolmetscher, a Bytecode Compiler, eine Optimierung nativen Code Compiler ein reversibler Debuggerund ein Paketmanager (OPAM). OCAML wurde ursprünglich im Kontext von entwickelt automatisierter Theorem beweisenund hat eine übergroße Präsenz in Statische Analyse und Formale Methoden Software. Über diese Bereiche hinaus hat es in ernsthaften Gebrauch in Systemprogrammierung, Web Entwicklung, und Finanztechnikunter anderem Anwendungsbereich.

Das Akronym Caml ursprünglich stand für Kategorische abstrakte Maschinensprache, aber Ocaml lässt dies aus abstrakte Maschine.[3] Ocaml ist a Kostenlose und Open-Source-Software Projekt verwaltet und hauptsächlich aufrechterhalten von der Französisches Institut für Forschung in Informatik und Automatisierung (Inria). In den frühen 2000er Jahren wurden Elemente aus OCAML von vielen Sprachen übernommen, insbesondere von OCAML F# und Scala.

Philosophie

Ml-Abgeleitete Sprachen sind am besten für ihre Statik bekannt Typsysteme und typern Compiler. Ocaml vereint funktional, Imperativ, und Objekt orientierte Programmierung Unter einem ML-ähnlichen Typ. Daher müssen Programmierer mit dem reinen funktionalen Sprachparadigma nicht sehr vertraut sein, um OCAML zu verwenden.

OCAML, indem der Programmierer innerhalb der Einschränkungen seines statischen Typsystems arbeiten muss Laufzeit Probleme im Zusammenhang mit dynamisch getippten Sprachen. Außerdem reduziert OCAMLs Typ-störender Compiler die Bedürfnisse der manuellen Anmerkungen, die in den meisten statisch typisierten Sprachen erforderlich sind, erheblich. Zum Beispiel die Datentypen von Variablen und der Unterschriften von Funktionen müssen normalerweise nicht explizit deklariert werden, wie in Sprachen wie Java und C#, weil sie aus den Operatoren und anderen Funktionen abgeleitet werden können, die auf die Variablen und anderen Werte im Code angewendet werden. Eine effektive Verwendung des Typs von OCAML kann eine gewisse Raffinesse eines Programmierers erfordern. Diese Disziplin wird jedoch mit zuverlässiger Hochleistungssoftware belohnt.

OCAML zeichnet sich vielleicht am meisten von anderen Sprachen mit Ursprung in der Wissenschaft durch ihren Schwerpunkt auf Leistung aus. Das statische Typ -System verhindert Fehlanpassungen vom Laufzeittyp und vermeidet somit den Laufzeit- und Sicherheitsüberprüfungen, die die Leistung dynamisch typisierter Sprachen belasten und gleichzeitig die Sicherheit der Laufzeit garantieren, außer wenn Array -Grenzen überprüfen wird ausgeschaltet oder wenn einige Typ-Unsafe-Funktionen wie wie Serialisierung werden verwendet. Diese sind selten genug, dass es in der Praxis durchaus möglich ist, sie zu vermeiden.

Abgesehen von der Art über dem Typ-Überkopf, Funktionelle Programmierung Sprachen sind im Allgemeinen eine Herausforderung, sich auf einen effizienten Code für Maschinensprachen zu erstellen, da Probleme wie die Funarg Problem. Zusammen mit Standardschleife, Registrieren und Anweisungen Optimierungen, Ocamls optimierender Compiler beschäftigt Statische Programmanalyse Methoden zur Optimierung des Werts Boxen und Schließung Zuordnung, die dazu beiträgt, die Leistung des resultierenden Codes zu maximieren, auch wenn er funktionale Programmierkonstrukte ausführlich verwendet.

Xavier Leroy hat erklärt, dass "OCAML mindestens 50% der Leistung eines anständigen C -Compilers liefert",[4] Obwohl ein direkter Vergleich unmöglich ist. Einige Funktionen in der OCAML -Standardbibliothek werden mit schnelleren Algorithmen als äquivalente Funktionen in den Standardbibliotheken anderer Sprachen implementiert. Zum Beispiel ist die Implementierung von Set Union in der OCAML -Standardbibliothek theoretisch asymptotisch schneller als die äquivalente Funktion in den Standardbibliotheken imperativen Sprachen (z. B. C ++, Java), da die OCAML -Implementierung die Unveränderlichkeit von Sätzen ausnutzt, um Teile der Input wiederverwenden zu setzt in der Ausgabe (siehe Persistente Datenstruktur).

Merkmale

OCAML -Funktionen a statisch Typ System, Geben Sie Inferenz ein, parametrischer Polymorphismus, Schwanzrekursion, Musteranpassung, erstklassige lexikalische Schließungen, Functors (parametrische Module), Ausnahmebehandlungund inkrementelle Generationen Automatische Müllsammlung.

OCAML ist bemerkenswert, dass sie den ML-Typ-Inferenz in einem Objektsystem in einer allgemeinen Sprache erweitert. Dies erlaubt strukturelle Subtyping, wo Objekttypen kompatibel sind, wenn ihre Methodensignaturen unabhängig von ihrer deklarierten Erbe kompatibel sind (eine ungewöhnliche Funktion in statisch typisierten Sprachen).

A Fremdenfunktionsschnittstelle zum Verknüpfung zu C Primitive werden zur Verfügung gestellt, einschließlich der Sprachunterstützung für effiziente numerische Arrays in Formaten kompatibel mit sowohl C als auch Forran. OCAML unterstützt auch das Erstellen von Bibliotheken von OCAML -Funktionen, die mit a verknüpft werden können hauptsächlich Programm in C, so dass eine OCAML -Bibliothek an C -Programmierer verteilt werden kann, die keine Kenntnisse oder Installation von OCAML haben.

Die OCAML -Verteilung enthält:

Der native Code -Compiler ist für viele Plattformen erhältlich, einschließlich Unix, Microsoft Windows, und Apfel Mac OS. Die Portabilität wird durch native erreicht Codegenerierung Unterstützung für große Architekturen: IA-32, X86-64 (AMD64), Leistung, Risc-v, ARM, und ARM64.[5]

OCAML -Bytecode und native Codeprogramme können in a geschrieben werden Multithread Stil, mit präventivem Kontextwechsel. Der Müllsammler des OCAML -Laufzeitsystems (das die einzige derzeit verfügbare vollständige Implementierung der Sprache ist) ist nicht für die Parallelität ausgelegt, und Symmetrische Multiprozessierung ist nicht unterstützt.[6] OCAML -Threads im selben Prozess werden nur durch Zeitfreigabe ausgeführt. Es gibt jedoch mehrere Bibliotheken für verteilte Computing wie z. Funktion und OCAMLNET/Plasma. Die OCAML 5.0 -Veröffentlichung (derzeit im Mai 2022 in der Entwicklung) wird die erste sein, die die Parallelität über unterstützt Wirkung von Handlern und Multicore -Parallelität.[7]

Entwicklungsumgebung

Seit 2011 sind viele neue Tools und Bibliotheken zur OCAML -Entwicklungsumgebung beigetragen:

  • Entwicklungswerkzeuge
    • opam ist ein Paketmanager für OCAML.
    • Merlin Bietet IDE-ähnliche Funktionen für mehrere Redakteure, einschließlich Typ Rückfall, Anlaufstelle und automatische Vervollständigung.
    • Düne ist ein komponierbares Build-System für OCAML.
    • Ocamlformat ist eine automatische Formatierung für OCAML.
    • ocaml-lsp-server ist ein Sprachserverprotokoll für ocaml Ide Integration.
  • Websites:
  • Alternative Compiler für OCAML:
    • JS_OF_OCAML, entwickelt vom Ocsifen -Team, ist ein optimierender Compiler von Ocaml bis JavaScript.
    • Bucklescript, was auch abzielt JavaScriptmit einem Fokus auf die Erzeugung lesbarer, idiomatischer JavaScript -Ausgabe.
    • OCAMLCC ist ein Compiler von OCAML bis C, um den nativen Code -Compiler für nicht unterstützte Plattformen zu ergänzen.
    • Ocamljava, entwickelt von Inria, ist ein Compiler von Ocaml bis zum Java virtuelle Maschine (JVM).
    • OCAPIC, entwickelt von LIP6, ist ein OCAML -Compiler für PIC -Mikrocontroller.

Codebeispiele

Snippets of Ocaml -Code können am einfachsten untersucht werden, indem sie in die eingeben Höchststufe Wiederholung. Dies ist eine interaktive OCAML -Sitzung, die die abgeleiteten Arten von resultierenden oder definierten Ausdrücken druckt.[8] Die ocaml oberste Ebene wird mit einfaches Ausführen des OCAML-Programms gestartet:

$ ocaml     Objektive CAML Version 3.09.0 # 

Der Code kann dann an der Eingabeaufforderung "#" eingegeben werden. Zum Beispiel um 1+2*3 zu berechnen:

# 1 + 2 * 3;; -: int = 7 

Ocaml färbt den Typ des Ausdrucks als "int" (a Maschinenpräzision ganze Zahl) und gibt das Ergebnis "7".

Hallo Welt

Das folgende Programm "Hello.ml":

print_endline "Hallo Welt!" 

Kann in eine ausführbare Bytecode zusammengestellt werden:

$ ocamlc hello.ml -o Hallo

oder in einem optimierten nativen Code zusammengestellt wurden: ausführbar:

$ ocamlopt hello.ml -o Hallo

und ausgeführt:

$ ./halloHallo Welt! $ 

Das erste Argument für OCAMLC, "Hello.ml", gibt die zum Kompilieren von Quellen angegeben und das Flag "-o Hello" gibt die Ausgabedatei an.[9]

Summieren einer Liste von Ganzzahlen

Listen sind einer der grundlegenden Datatypen in OCAML. Das folgende Code -Beispiel definiert a rekursiv Funktion Summe das akzeptiert ein Argument, Ganzzahlen, was eine Liste von Ganzzahlen sein soll. Beachten Sie das Schlüsselwort Rec Was bedeutet, dass die Funktion rekursiv ist. Die Funktion itersiv über die angegebene Liste der Ganzzahlen und liefert eine Summe der Elemente. Das passen Aussage hat Ähnlichkeiten zu C's Schalter Element, obwohl es weitaus allgemeiner ist.

Lassen Rec Summe Ganzzahlen =  ( * Keyword Rec bedeutet 'rekursiv'. *)  passen Ganzzahlen mit  | [] -> 0  (* Ergeben 0, wenn Ganzzahlen der leer sind                                              aufführen []. *)  | Erste :: sich ausruhen -> Erste + Summe sich ausruhen;;  (* Rekursiver Anruf, wenn Ganzzahlen ein nicht ist                                             leere Liste; Erstens ist das erste                                              Element der Liste und Ruhe ist a                                              Liste der restlichen Elemente,                                              möglicherweise []. *) 
  # Summe [1;2;3;4;5] ;;  - : int = 15 

Eine andere Möglichkeit besteht darin, Standard zu verwenden falten Funktion Das funktioniert mit Listen.

Lassen Summe Ganzzahlen =  Aufführen.fold_left (Spaß Akkumulator x -> Akkumulator + x) 0 Ganzzahlen;; 
  # Summe [1;2;3;4;5] ;;  - : int = 15 

Seit der Anonyme Funktion Ist einfach die Anwendung des + Operators, dies kann verkürzt werden auf:

Lassen Summe Ganzzahlen =  Aufführen.fold_left (+) 0 Ganzzahlen 

Darüber hinaus kann man das Listenargument auslassen, indem man a verwendet teilweise Anwendung:

Lassen Summe =  Aufführen.fold_left (+) 0 

Schnelle Sorte

OCAML eignet sich dazu, rekursive Algorithmen präzise auszudrücken. Das folgende Code -Beispiel implementiert einen ähnlichen Algorithmus wie schnelle Sorte Dies sortiert eine Liste in zunehmender Reihenfolge.

 Lassen Rec QSORT = Funktion  | [] -> []  | Drehzahl :: sich ausruhen ->  Lassen ist weniger x = x < Drehzahl in  Lassen links, Rechts = Aufführen.Trennwand ist weniger sich ausruhen in  QSORT links @ [Drehzahl] @ QSORT Rechts 

Geburtstagsproblem

Das folgende Programm berechnet die geringste Anzahl von Personen in einem Raum, für den die Wahrscheinlichkeit von völlig einzigartigen Geburtstagen weniger als 50% beträgt (die Geburtstagsproblem, wo für 1 Person die Wahrscheinlichkeit 365/365 (oder 100%) beträgt, für 2 ist sie 364/365, für 3 ist es 364/365 × 363/365 usw.) (Antwort = 23).

Lassen Jahr_Size = 365. Lassen Rec birthday_paradox Prob Personen =  Lassen Prob = (Jahr_Size -. schweben Personen) / Jahr_Size *. Prob  in  wenn Prob < 0.5 dann  Printf.printf "Antwort = %d\n" (Personen+1)  anders  birthday_paradox Prob (Personen+1) ;; birthday_paradox 1.0 1 

Kirchliche Ziffern

Der folgende Code definiert a Kirchenkodierung von natürliche Zahlen, mit Nachfolger (ProCon) und Addition (Add). Eine Kirchenzumal n ist ein Funktion höherer Ordnung Das akzeptiert eine Funktion f und ein Wert x und gilt f zu x exakt n mal. Um eine kirchliche Ziffer von einem funktionalen Wert in eine Zeichenfolge umzuwandeln, übergeben wir eine Funktion, die die Zeichenfolge vorbereitet "S" zu seiner Eingabe und der konstanten Zeichenfolge "0".

Lassen Null f x = x Lassen Succ n f x = f (n f x) Lassen eines = Succ Null Lassen zwei = Succ (Succ Null) Lassen hinzufügen N1 N2 f x = N1 f (N2 f x) Lassen to_string n = n (Spaß k -> "S" ^ k) "0" Lassen _ = to_string (hinzufügen (Succ zwei) zwei) 

Schiedsrichter-Präzisionsfaktorfunktion (Bibliotheken)

Eine Vielzahl von Bibliotheken ist direkt von OCAML aus zugänglich. Zum Beispiel hat OCAML eine integrierte Bibliothek für willkürliche Präzisionsarithmetik. Wenn die faktorielle Funktion sehr schnell wächst, überflutet sie die Maschinenpräzisionszahlen (typischerweise 32 oder 64 Bit). Daher ist Faktor ein geeigneter Kandidat für die arbitäre Arithmetik.

In OCAML liefert das Num-Modul (jetzt vom Zarith-Modul ersetzt) ​​beliebige Arithmetik und kann mit:

# #verwenden "Topfind";; # #benötigen "num";; # offen Num;; 

Die faktorielle Funktion kann dann mit den beliebigen numerischen Operatoren geschrieben werden =/, */ und -/:

# Lassen Rec Tatsache n =  wenn n =/ Int 0 dann Int 1 anders n */ Tatsache(n -/ Int 1) ;; val Tatsache : Num.num -> Num.num = <Spaß> 

Diese Funktion kann viel größere Faktorien berechnen, wie z. B. 120 !:

# string_of_num (Tatsache (Int 120)) ;; - : Saite = "668950291344912705758811805409037258675274633313802981029567135230163 55724496298936687416527198498130815763789321409055253440858940812185989 848111438965000596496052125696000000000000000000000000 " 

Dreieck (Grafik)

Das folgende Programm macht ein rotierendes Dreieck in 2D mit Verwendung OpenGL:

Lassen () =  ignorieren (Glut.drin Sys.argv);  Glut.InitDisplayMode ~double_buffer:Stimmt ();  ignorieren (Glut.Createwindow ~Titel:"OpenGL -Demo");  Lassen Winkel t = 10. *. t *. t in  Lassen machen () =  Glclear.klar [ `Farbe ];  GLMAT.load_identity ();  GLMAT.drehen ~Winkel: (Winkel (Sys.Zeit ())) ~z:1. ();  Gldraw.beginnt `Dreiecke;  Aufführen.Iter Gldraw.Scheitelpunkt 2 [-1., -1.; 0., 1.; 1., -1.];  Gldraw.endet ();  Glut.Swapbuffer () in  GLMAT.Modus `ModelView;  Glut.DisplayFunc ~CB:machen;  Glut.idlefunc ~CB:(Etwas Glut.postreDrisplay);  Glut.Hauptschleife () 

Die Lablgl -Bindungen an OpenGL sind erforderlich. Das Programm kann dann zu Bytecode zusammengestellt werden mit:

  $ ocamlc -i +lablgl lablglut.cma lablgl.cma einfach.ml -o einfach

oder zu nativecode mit:

  $ ocamlopt -i +lablgl lablglut.cmxa lablgl.cmxa Simple.ml -o einfach

Oder einfacher mit dem Befehl ocamlfind Build

  $ ocamlfind opt Simple.ml -package lablgl.glut -linkpkg -o einfach

und Renn:

  $ ./simple

In OCAML können weitaus ausgefeiltere 2D- und 3D-grafische Programme mit leistungsstärkerem Leistung entwickelt werden. Dank der Verwendung von OpenGL und OCAML können die resultierenden Programme plattformübergreifend sein und auf vielen wichtigen Plattformen ohne Änderungen zusammenstellen.

Fibonacci-Folge

Der folgende Code berechnet die Fibonacci-Folge einer Zahl n eingegeben. Es verwendet Schwanzrekursion und Musteranpassung.

Lassen Flunkerei n =  Lassen Rec fib_aux m a b =  passen m mit  | 0 -> a  | _ -> fib_aux (m - 1) b (a + b)  in fib_aux n 0 1 

Funktionen höherer Ordnung

Funktionen können Funktionen als Eingabe- und Rückgabefunktionen als Ergebnis annehmen. Zum Beispiel anwenden zweimal zu einer Funktion f ergibt eine Funktion, die gilt f zweimal zu seinem Argument.

Lassen zweimal (f : 'a -> 'a) = Spaß (x : 'a) -> f (f x) ;; Lassen Inc. (x : int) : int = x + 1;; Lassen Add2 = zweimal Inc.;; Lassen INC_STR (x : Saite) : Saite = x ^ "" " ^ x;; Lassen add_str = zweimal(INC_STR) ;; 
  # Add2 98;;   - : int = 100   # add_str "Prüfen";;   - : Saite = "Testerentesttest" 

Die Funktion zweimal Verwendet eine Typvariable 'a um anzuzeigen, dass es auf jede Funktion angewendet werden kann f Mapping von einem Typ 'a für sich selbst, anstatt nur zu int-> int Funktionen. Im Speziellen, zweimal kann sogar auf sich selbst angewendet werden.

  # Lassen vier Mal f = (zweimal zweimal) f;;   val vier Mal : ('a -> 'a) -> 'a -> 'a = <Spaß>   # Lassen Add4 = vier Mal Inc.;;   val Add4 : int -> int = <Spaß>   # Add4 98;;   - : int = 102 

Abgeleitete Sprachen

Metaocaml

Metaocaml[10] ist ein Mehrstufige Programmierung Erweiterung der OCAML, die eine inkrementelle Kompilierung von neuem ermöglicht Maschinensprache Während der Laufzeit. Unter bestimmten Umständen sind erhebliche Beschleunigungen mit mehrstufiger Programmierung möglich, da detailliertere Informationen über die zu verarbeitenden Daten zur Laufzeit verfügbar sind als zur regulären Kompilierungszeit, sodass der inkrementelle Compiler viele Fälle von Bedingungsprüfung usw. optimieren kann.

Als Beispiel: Wenn zur Kompilierung der Zeit bekannt ist, dass einige Leistungsfunktion x -> x^n wird oft benötigt, aber der Wert von n Es ist nur zur Laufzeit bekannt, eine zweistufige Leistungsfunktion kann in Metaocaml verwendet werden:

 Lassen Rec Energie n x =  wenn n = 0  dann . <1>.  anders  wenn eben n  dann sqr (Energie (n/2) x)  anders . <. ~x *. . ~ (Energie (n - 1) x)>. 

Sobald n Es ist zur Laufzeit bekannt, eine spezielle und sehr schnelle Leistungsfunktion kann erstellt werden:

 . <Spaß x -> . ~ (Energie 5 . <x>.)>. 

Das Ergebnis ist:

 Spaß x_1 -> (x_1 *  Lassen y_3 =   Lassen y_2 = (x_1 * 1)  in (y_2 * y_2)  in (y_3 * y_3)) 

Die neue Funktion wird automatisch zusammengestellt.

Andere abgeleitete Sprachen

  • Atomcaml liefert eine Synchronisationsprimitive für die Atomausführung von Code (Transaktion).
  • Emily (2006) handelt Objektkapazitätsmodell Sicherheit Prinzipien.
  • F# ist ein .NET Framework Sprache basierend auf OCAML.
  • Frische OCAML erleichtert die Manipulation von Namen und Bindemitteln.
  • GCAML fügt OCAML Erweiterungspolymorphismus hinzu, wodurch Überladung und Typen-Safe-Marshalle ermöglicht werden.
  • Jocaml Integriert Konstruktionen zur Entwicklung gleichzeitiger und verteilter Programme.
  • OCAMLDUCE erweitert OCAML mit Merkmalen wie XML-Ausdrücken und regulären Expressionstypen.
  • Ocamlp3l ist a Parallele Programmierung System basierend auf OCAML und der P3L -Sprache.
  • Obwohl nicht wirklich eine separate Sprache, Grund ist eine alternative OCAML Syntax und Toolchain Für Ocaml erstellt bei Facebook.

Software in OCAML geschrieben

Benutzer

Mehrere Dutzend Unternehmen verwenden OCAML in gewissem Maße.[16] Bemerkenswerte Beispiele sind:

Verweise

  1. ^ "Module". Abgerufen 22. Februar 2020.
  2. ^ "OCAML 4.14.0 Versionsnotizen". Abgerufen 27. Mai 2022.
  3. ^ "Eine Geschichte von Ocaml". Abgerufen 24. Dezember 2016.
  4. ^ Linux Weekly News.
  5. ^ "OCAML/ASMCOMP AT SCHLAGN · OCAML/OCAML · GitHub". GitHub. Abgerufen 2. Mai 2015.
  6. ^ "Archive der CAML -Mailingliste> Nachricht von Xavier Leroy". Abgerufen 2. Mai 2015.
  7. ^ "OCAML Multicore -monatliche Updates".
  8. ^ "OCAML - Das Toplevel -System oder repl (ocaml)". ocaml.org. Abgerufen 2021-05-17.
  9. ^ "OCAML - Batch Compilation (OCAMLC)".
  10. ^ OLEG-AT-OKMIJ.org. "Ber Metaocaml". okmij.org.
  11. ^ "Messenger.com jetzt zu 50% in die Vernunft umgewandelt · Grund". ReasonMl.github.io. Abgerufen 2018-02-27.
  12. ^ "Fluss: Ein statischer Typ Checker für JavaScript". Fließen.
  13. ^ "Statischer Analysator schließen". Schließen.
  14. ^ "Github-Facebook/Pyre-Check: Performant-Typ-Prüfungen für Python". 9. Februar 2019 - über Github.
  15. ^ "WebAssembly/Spec: WebAssembly -Spezifikation, Referenz -Interpreter und Testsuite". World Wide Web Konsortium. 5. Dezember 2019. Abgerufen 2021-05-14 - über Github.
  16. ^ "Unternehmen, die OCAML nutzen". Ocaml.org. Abgerufen 2021-05-14.
  17. ^ "Bucklescript: Die Veröffentlichung von 1.0 ist angekommen! | Tech bei Bloomberg". Technologie bei Bloomberg. 8. September 2016. Abgerufen 21. Mai 2017.
  18. ^ Yaron Minsky (1. November 2011). "OCAML für die Massen". Abgerufen 2. Mai 2015.

Externe Links