- Mit Elixir 1.19 lassen sich durch ein stärkeres Typsystem und verbesserte Compiler-Performance mehr Bugs schneller erkennen
- Die Typinferenz wurde auf anonyme Funktionen und Protokolle ausgeweitet, wodurch eine deutlich umfassendere automatische Prüfung auch ohne Typannotationen der Nutzer möglich ist
- In großen Projekten wird eine bis zu 4-fach höhere Kompiliergeschwindigkeit erreicht, einschließlich Optimierungen bei paralleler Kompilierung und Code-Laden
- Auch das Ökosystem und die Transparenz der Lieferkette wurden gestärkt, unter anderem durch Unterstützung für Erlang/OTP 28 und die Einführung der OpenChain-Zertifizierung
- Darüber hinaus sind zahlreiche weitere Funktionen enthalten, etwa verbessertes Option Parsing, bessere Debug-Eigenschaften von ExUnit und eine verbesserte Zugänglichkeit shell-basierter Dokumentation
Wichtige Verbesserungen in Elixir 1.19
Verbesserungen am Typsystem
Typinferenz für alle Bestandteile
- Type inference (Typinferenz) ist eine Funktion, die den Typ von Ausdrücken zur Compile-Zeit automatisch bestimmt
- Bisher sollte die Typinferenz vor allem für Pattern, Guards und Rückgabewerte unterstützt werden, in diesem Release wurde jedoch Typinferenz für alle Bestandteile (außer Guards) eingeführt
- Da bei der Typinferenz auch Funktionsaufrufe innerhalb von Modulen sowie Aufrufe von Funktionen der Elixir-Standardbibliothek berücksichtigt werden, können Funktionen, die früher als
dynamic() -> boolean() inferiert wurden, nun präziser als etwa integer() -> boolean() inferiert werden
- Typinferenz bringt verschiedene Trade-offs mit sich, etwa bei Kompiliergeschwindigkeit, Ausdrucksstärke, inkrementeller Kompilierung und Klarheit von Fehlermeldungen; künftig sollen daher auch Guard-Typinferenz und Typinformationen aus Abhängigkeiten einbezogen werden
- Wenn für eine Funktion eine Typsignatur explizit angegeben ist, arbeitet das System nicht mit Typinferenz, sondern mit einer expliziten Typprüfung, die nur Typen zulässt, die zur Annotation des Nutzers passen
Typprüfung bei Protokoll-Dispatch und Implementierungen
- Elixir wendet jetzt Typprüfungen bei Protokollaufrufen und -implementierungen an
- Wird zum Beispiel ein Typ, der das Protokoll
String.Chars nicht implementiert, an String-Interpolation übergeben, wird eine Warnmeldung ausgegeben
- Auch in for comprehensions wird eine Warnung erzeugt, wenn ein Typ, der das Protokoll
Enumerable nicht erfüllt, als Generator übergeben wird
- Mit diesen Typprüfungen lassen sich mehr Bugs bereits zur Compile-Zeit verhindern
Typinferenz und -prüfung für anonyme Funktionen
- Elixir 1.19 unterstützt Typinferenz und Typprüfung für anonyme Funktionen
- Wird etwa an eine anonyme Funktion, die den Typ
%{} erwartet, ein falscher Typ wie "hello" übergeben, kann das sofort als Warnung zur Compile-Zeit erkannt werden
- Auch bei Function Captures (
&String.to_integer/1 usw.) wird Typinferenz angewendet, wodurch der Umfang automatisierter Typprüfung erweitert wird
Referenzen und Partner
- Dieses Typsystem wurde in einer Partnerschaft zwischen CNRS und Remote entwickelt
- Fresha, *Starfish* *, Dashbit und weitere haben das Projekt unterstützt
Schnellere Kompilierung in großen Projekten
Beseitigung von Bottlenecks beim Code-Laden
- Bisher wurden Module direkt nach ihrer Definition geladen, in diesem Release wurde dies auf eine Lazy-Loading-Strategie umgestellt
- Dadurch wird der Code-Server entlastet, die parallele Kompilierung verbessert und die Kompiliergeschwindigkeit großer Projekte um mehr als das Doppelte erhöht
- Zwei wichtige Hinweise:
- Wenn während der Kompilierung ein separater Prozess erzeugt wird und dieser auf Module desselben Projekts zugreift, kann das Laden ausbleiben; als Workaround können
Kernel.ParallelCompiler.pmap/2 oder Code.ensure_compiled!/1 verwendet werden
- Innerhalb eines
@on_load-Callbacks kann beim Aufruf von Modulen desselben Projekts ein Fehler auftreten; falls nötig, kann die Option @compile {:autoload, true} verwendet werden
- In beiden Fällen konnten früher nicht deterministische Kompilierfehler auftreten, mit dieser Verbesserung wird nun jedoch eine deterministische (reproduzierbare) Kompilierumgebung gewährleistet
Parallele Kompilierung von Abhängigkeiten
- Über die Umgebungsvariable
MIX_OS_DEPS_COMPILE_PARTITION_COUNT wird die parallele Kompilierung von Abhängigkeiten unterstützt
- Da mehrere OS-Prozesse gleichzeitig verwendet werden, um Abhängigkeiten parallel zu kompilieren, kann sich die Kompilierleistung je nach Projektgröße und Anzahl der CPU-Kerne um bis zu das 4-Fache verbessern
- Experimentell hat sich gezeigt, dass ein Wert von etwa der Hälfte aller verfügbaren Kerne für die Ressourcennutzung effektiv ist
- Durch die Parallelisierung kann sich der Speicherverbrauch erhöhen, weshalb bei der Nutzung in CI oder auf Build-Servern Vorsicht geboten ist
Unterstützung für Erlang/OTP 28
- Elixir 1.19 unterstützt offiziell Erlang/OTP 28.1+
- Aufgrund von Änderungen an der Darstellung regulärer Ausdrücke in Erlang/OTP 28 können reguläre Ausdrücke nicht mehr als Standardwert in Structs verwendet werden
- Bei der Initialisierung von Structs können reguläre Ausdrücke weiterhin verwendet werden
Einführung der OpenChain-Zertifizierung
- Dieses Release ist die erste Version, die mit der Einhaltung des OpenChain-Standards beginnt
- Jedes Release enthält ein SBoM (Source Bill of Materials) im Format CycloneDX 1.6/SPDX 2.3
- Das erhöht die Transparenz der Lieferkette bei Release-Bestandteilen und Lizenzen und trägt zu einer strengeren Verwaltung bei
- Diese Arbeit wurde von Jonatan Männchen durchgeführt und von der Erlang Ecosystem Foundation unterstützt
Weitere Verbesserungen
- Hinzu kommen verschiedene Verbesserungen an Tools und Bibliotheken, darunter Option Parsing, Debugging und Performance von ExUnit sowie die Zugänglichkeit shell-basierter Dokumentation
- Ausführlichere Release Notes finden sich im CHANGELOG
1 Kommentare
Hacker-News-Kommentare
Es wird betont, dass die schrittweise Einführung automatischer Typprüfung in Elixir ein hervorragendes Beispiel für eine Sprachverbesserung ist, an dem sich auch andere Programmiersprachen orientieren können; es gab viele Fälle, in denen Ökosysteme durch große Veränderungen in zwei Lager gespalten wurden, und es ist beruhigend, dass José bereits 2018 klar gesagt hat, dass die Sprache selbst im Wesentlichen fertig ist; Sprache und Core werden nicht mehr aufbrechend verändert, was viel Stabilität vermittelt. Empfohlen wird auch dieser Vortrag. Die konsistente und hervorragende Steuerung beeindruckt.
Elixir liefert weiterhin konstant großartige Funktionen und Verbesserungen und entwickelt sich stabil weiter. Die Spracharchitektur ist hervorragend, und die Gründer geben kontinuierlich die richtige Richtung vor; wirklich beeindruckend. Schade ist eher, dass man im Alltag nicht öfter Gelegenheit hat, Elixir zu verwenden.
Es werden experimentelle Daten zur Kompiliergeschwindigkeit von Phoenix-Abhängigkeiten geteilt. Auf einem Mac M1 Max wurden bei einer kleinen App, die nur die Standard-Phoenix-Abhängigkeiten enthält, je nach Wert der Umgebungsvariable
MIX_OS_DEPS_COMPILE_PARTITION_COUNTfolgende Kompilierzeiten gemessen:Dazwischen wurde jedes Mal mit dem Befehl
rm -rf _buildder Cache gelöscht._buildkeine Spuren verblieben.In den letzten Monaten habe ich Gleam wirklich schätzen gelernt. Ich begrüße zwar auch die Einführung eines Typsystems in Elixir, aber genau dieser Punkt war früher ein Hauptgrund, Elixir nicht zu übernehmen. Ich würde Elixir irgendwann gern noch einmal ausprobieren, habe aber die Sorge, dass es am Ende wie bei JavaScript mit TypeScript nur äußerlich typisiert ist und in vielen Libraries oder Paketen doch alles als dynamic/any endet. Ich frage mich, ob diese Sorge unbegründet ist. BEAM ist wirklich großartig.
Elixir wirkt auf mich wie die vielversprechendste Umgebung für Webentwicklung. Jedes Mal, wenn ich im Berufsalltag auf Organisationen oder Teams treffe, die Elixir nutzen, scheint ihr Niveau höher zu sein als gewöhnlich. Ich denke, Elixir gibt in Umgebungen mit kontinuierlicher Weiterentwicklung weiterhin Richtung und Standards vor.
Es wird vorgestellt, dass das Elixir-Release nun Source-SBoM-Formate ab CycloneDX 1.6 und SPDX 2.3 unterstützt. Es ist wirklich großartig, dass SBOM-Management auf Sprachebene stattfindet. Leider nutzt mein aktuelles Unternehmen Elixir nicht.
Wer zu einem praxisnahen Open-Source-Elixir-Projekt beitragen möchte: Eine frühere Hauptkomponente von Mozilla Hubs wird als eigenständiges Projekt weiterhin in Elixir entwickelt, siehe Hubs Foundation/reticulum.
Auf Basis der Elixir-Standardbibliothek ist eine Compile-Time-Typinferenz möglich, die in anwendungsspezifischen Situationen dynamische Typen als Boolesche Werte oder etwa Integer als Boolesche Werte behandeln kann.
Ich habe keine Erfahrung in der Elixir-Entwicklung, bin aber ein Fan. Früher mochte ich die Praxisnähe und Schönheit von Ruby, habe dann aber wegen meiner Begeisterung für Typsysteme die Sprache gewechselt. Sowohl Elixir als auch Ruby haben Typsysteme eingeführt, aber heute nutze ich meist Kotlin, das sich syntaktisch wie „typisiertes Ruby“ anfühlt.
Ich nutze Soketi zusammen mit dem Pusher-SDK für Event-Broadcasting. Die App hat eine gemischte Struktur aus Echtzeit- und REST-Endpunkten, und die Last durch Echtzeitberechnungen ist nicht besonders hoch, aber falls nötig würde ich diesen Teil separat in Go umsetzen. Demnächst sollen auch Kollaborationsfunktionen hinzukommen, und ich frage mich, ob es in so einer Situation sinnvoll ist, Phoenix einzuführen.