Grain
Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:
Ubuntu 22.04 Jammy Jellyfish
Du möchtest den Artikel für eine weitere Ubuntu-Version testen? Mitarbeit im Wiki ist immer willkommen! Dazu sind die Hinweise zum Testen von Artikeln zu beachten.
Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:
Grain 🇬🇧 ist eine in der Programmiersprache ReasonML 🇬🇧 entwickelte Programmiersprache. Dabei ist sie ein Vertreter der Funktionalen Programmiersprachen, die sich von weiteren Programmiersprachen durch die besondere Behandlung von Funktionen unterscheiden. Zu den Vertretern dieser Sprache gehören neben Grain z.B. auch Scala und Haskell. Grain setzt sich zum Ziel 🇬🇧, durch viele Verbesserungen und Anpassungen einem Anspruch als „Programmiersprache des neuen Zeitalters“ gerecht zu werden.
Dadurch, das Grain mittels des Binaryen Compiler Toolkit in den Standard WebAssembly übersetzt wird, ist die Programmiersprache flexibel einsetzbar, was von Seiten der Entwickler besonders betont wird.
Installation¶
Grain ist nicht in den Paketquellen enthalten und auch nicht als Snap-Paket, Flatpak o.ä. verfügbar. Auf der Projektseite sind aber vorkompilierte Binärdateien für x86_64-Systeme verfügbar, die manuell installiert werden kann.
Zur Installation lädt man zuerst von der Releaseseite des Projekts die Datei grain-linux-64 herunter.
Möchte man Grain nur für sich selber nutzen, verschiebt man die Datei ins Verzeichnis /home/BENUTZERNAME/.local/bin, benennt diese nach grain um und macht sie ausführbar[4].
Hinweis:
/home/BENUTZERNAME/.local/bin muss zusätzlich noch der Umgebungsvariablen PATH
hinzugefügt werden, damit die dort gespeicherten, ausführbaren Programme auch gefunden werden.
Für die systemweite Installation verschiebt man die Datei mit Root-Rechten[2] ins Verzeichnis /usr/local/bin, benennt diese nach grain um und macht sie ausführbar[2][4].
Nutzung¶
Das zentrale Programm zum Kompilieren von Grain Code nach WASM ist grain
. Die allgemeine Syntax lautet:
grain [KOMMANDO] [OPTIONEN] PROGRAMNAME
Per Konvention sollen Grainprogramme die Endung .gr haben.
Der Befehl
grain mein_programm.gr
kompiliert den Code aus mein_programm.gr nach WASM, erzeugt im gleichen Verzeichnis die binäre Datei mein_programm.gr.wasm und führt diese direkt aus.
grain
kennt eine ganze Reihe von Optionen und Kommandos:
Kommandos und Optionen von grain | |
Option | Erkläriung |
-o DATEINAME | Kompiliert das Programm und speichert es unter dem Name DATEINAME ab. |
--release | Führt beim Kompilieren Optimierungen durch, was zu (deutlich) kleineren und schneller ausführbaren WASM-Dateien führt. Der Kompilierungsvorgang dauert dann länger. |
--elide-type-info | Der kompilierte Code enthält keine Informationen zu Datentypen, die zur Laufzeit verfügbar sind. Diese Optionen kann man immer dann nutzen, wenn der Code keine print und toString Befehle mehr enthält. |
Kommando | Erklärung |
compile PROGRAMM.gr | Kompiliert PROGRAMM.gr nach WASM, führt das Programm aber nicht aus. |
run PROGRAMM.wasm | Führt das bereits nach WASM kompilierte Programm PROGRAMM.wasm aus. |
format PROGRAMM.gr | Formatiert das Grainprogramm PROGRAMM.gr gemäß den Empfehlungen der Grainentwickler. |
Zum Übersetzen von Code, der dann auch produktiv eingesetzt wird, empfiehlt sich in der Regel:
grain compile --elide-type-info --release PROGRAMMNAME.gr
grain kennt noch eine ganze Reihe weiterer Optionen und einige weitere Kommandos. Details dazu sind in der grain cli 🇬🇧 Dokumentation zu finden.
"Hallo Welt" Beispiel¶
Im folgenden ein minimales Beispielprogramm in Grain:
1 2 3 4 5 | //helloworld.gr print("Hello from the Grain language!") let number = 42 print(toString(number)) |
Die 1. Zeile ist ein Kommentar, die 2. Zeile gibt den String "Hello from the Grain language!" aus. Die fünfte Zeile weist der Variablen number
den Wert 42 zu, in der 6. Zeile wird die Zahl 42 in einen String umgewandelt und ausgeben.
Die Ausgabe des Programms ist:
Hello from the Grain language! 42
umfangreicheres Beispiel¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | //umfangreicheres Beispiel Grain Code import String from "string" import {add} from "number" let solution = 42 let output = String.concat("The answer is: ", toString(solution)) print(output) let double = (x) => { add(x, x) } let doubleFour = double(4) print(doubleFour) let isEven = (a) => { if (a % 2 == 0) { true } else { false } } let mut result = isEven(6) print(result) result = isEven(7) print(result) enum UbuntuNicks { Bionic, Focal, Jammy, Kinetic } let checkNick = (nick) => { match(nick) { Focal => "April 2020", Jammy => "April 2022", _ => "valid nickname, but I don't know the release date..." } } let mut releaseDate = checkNick(Jammy) print(releaseDate) releaseDate = checkNick(Kinetic) print(releaseDate) |
(Kurze) Erklärung des Codes:
In Zeile 3 und 4 werden Module bzw. Funktionen daraus importiert. Zuerst wird das komplett
string
Modul importiert, dann die Funktionadd
aus demnumbers
Modul.+In Zeile 7 bis 9 wird zuerst die Variable
solution
definiert, dann der Variablenoutput
ein verketteter String zugewiesen, in Zeile 9 erfolgt die Ausgabe. Variablenzuweisung sind in Grain standardmäßig unveränderlich, d.h.solution
behält immer den Wert42
.In Zeile 11 bis 13 wird die Funktion
double
definiert. Diese nimmt eine Wert entgegen, addiert diesen mit sich selber und gibt ihn zurück. Grain kennt kein explizitesreturn
oder ähnliches. Das Ergebnis der letzten ausgeführten Zeile einer Funktion wird immer zurückgegeben.In den Zeilen 15 und 16 wird die Funktion
double
mit dem Wert4
aufgerufen und das Ergebnis ausgegeben.In den Zeile 18 bis 24 wird eine weitere Funktionen names
isEven
definiert, die prüft, ob eine übergebene Zahl gerade oder ungerade ist. In der Funktion wirdif else
genutzt.In den Zeilen 26 bis 29 wird die Funktion
isEven
zweimal mit verschiedenen Werten aufgerufen. In der Zeile 26 wird mitlet mut ...
die Variableresult
explizit als veränderlich definiert. In der Zeile 28 wirdresult
dann ein neuer Wert zugeordnet.In Zeile 31 wird die Variable
UbuntuNicks
vom Typ enum definiert und dieser eine Reihe von Werten zugewiesen.In den Zeilen 33 bis 39 wird einen weitere Funktion namens
checkNick
definiert, in der Pattern Matching 🇬🇧 zum Einsatz kommt.In Zeile 41 bis 44 wird die Funktion
checkNick
zweimal aufgerufen.
mehr Beispiele und Dokumentation¶
Ein etwas umfangreichere Einführung erhält man im Grain Guide 🇬🇧 und in der Dokumentation. Dort ist auch die komplette Standardbibliothek 🇬🇧 von Grain dokumentiert.
Flexibilität von Grain¶
Dadurch, das Grain nach WebAssembly (WASM) kompiliert wird 🇬🇧, ist es flexibel einsetzbar, unter anderem auch im Terminal und Browsern, worauf sich die Dokumentation 🇬🇧 konzentriert.
Versionen des Grain CLI enthalten die Laufzeitumgebung, WASI (WebAssembly Interface), bereits. Möchte man mittels Grain erstelltes WebAssembly aber im Browser laufen lassen, muss sichergestellt werden, dass die Laufzeitumgebung vorhanden ist.
Deinstallation¶
Zur Deinstallation löscht man einfach die Datei grain aus dem Verzeichnis, in das man sie abgelegt hat, also /usr/local/bin oder /home/BENUTZERNAME/.local/bin.
Links¶
Webseite 🇬🇧 von Grain
Online-Dokumentation 🇬🇧 von Grain
Projektseite bei Github