1 Punkte von GN⁺ 2 시간 전 | 2 Kommentare | Auf WhatsApp teilen
  • Janet ist ein kleiner Lisp-Dialekt, lässt sich aber dank imperativer Spracheigenschaften, First-Class-Funktionen, eines einzigen Identifier-Namespace und lexikalischem Block-Scope einfach erlernen
  • Die Kernsprache besteht nur aus 8 Befehlen: do, def, var, set, if, while, break, fn; Makros liefern stärkere oder bequemere Wrapper für Kontrollfluss auf höherer Ebene
  • Die Bereitstellbarkeit wird dadurch erreicht, dass Janet-Programme zu nativen Executables kompiliert werden, die statisch mit der Janet-Runtime gelinkt sind, sodass Nutzer weder Janet noch Abhängigkeiten installieren müssen
  • Parsing Expression Grammars (PEG) sind einfacher, mächtiger und vorhersagbarer als reguläre Ausdrücke, und sh erlaubt es, Pipes und Redirects direkt in Janet auszudrücken, was den Einsatzbereich beim Schreiben von CLI-Tools erweitert
  • Compile-Time-Ausführung führt Top-Level-Befehle zuerst aus und speichert dann einen Snapshot des Programmzustands auf die Festplatte, sodass sich auch ohne Makros Werte, geteilte Referenzen, Generatoren und Closure-Zustände in die Runtime übernehmen lassen

Ein einfacher Kern

  • Janet ist eine imperative Sprache mit First-Class-Funktionen, einem einzigen Identifier-Namespace und lexikalischem Block-Scope
  • Der Sprachkern bleibt mit nur 8 Befehlen klein: do, def, var, set, if, while, break, fn
  • Makros ermöglichen stärkere oder bequemere High-Level-Wrapper für Kontrollfluss
  • Die Runtime-Semantik ist vertraut, und auch der Rest der Sprache ist klein genug, dass die komplette Standardbibliothek auf eine einzige Seite passt

Native Bereitstellung und Embedding

  • Janet-Programme lassen sich einfach zu nativen Executables kompilieren, die statisch mit der Janet-Runtime gelinkt sind
  • Nutzer, die ein solches Programm erhalten, müssen weder Janet noch Projektabhängigkeiten oder andere separate Komponenten installieren
  • Janet kompiliert sich selbst zu Bytecode, schreibt diesen Bytecode dann in eine .c-Datei, die die Janet-Runtime startet, und kompiliert diese C-Datei mit dem systemeigenen C-Compiler
  • Ein einfaches natives „hello world“-Binary ist kleiner als 1 MB; bei Janet 1.27.0 auf aarch64 macOS waren es 784K
  • Dieses Binary enthält die komplette Janet-Runtime, den Garbage Collector und sogar den Bytecode-Compiler, sodass sich auch Programme bauen lassen, die Janet-Code zur Laufzeit auswerten
  • Die Janet-Runtime ist eine kleine C-Bibliothek; nach dem Linken kann man Janet-Werte durch Aufruf gewöhnlicher C-Funktionen manipulieren
  • Janet lässt sich auch in Websites einbetten und kann statische Seiten mit benutzerdefinierten programmierbaren DSLs bereitstellen, wie bei Toodle

Text-Parsing und Subprozess-DSL

  • Die Textverarbeitung von Janet basiert statt auf regulären Ausdrücken auf Parsing Expression Grammars
  • Parsing Expression Grammars sind einfacher, mächtiger und vorhersagbarer als reguläre Ausdrücke und nicht an einzelne Zeilen gebunden, sodass sich auch mehrzeiliger Text parsen lässt
  • Damit lassen sich HTML, JSON und andere nicht-reguläre Sprachen parsen sowie binäre Dateiformate mit beliebigen Null-Bytes verarbeiten
  • sh ist ein Shell-Scripting-DSL eines Drittanbieters, mit dem sich Pipes und Redirects direkt in Janet-Code ausdrücken lassen
($ find . -name *.janet | say)
  • Dieses DSL macht Janet von einer vernünftigen Alternative zu Perl zu einer vernünftigen Alternative zu Bash für ein ziemlich breites Spektrum an Programmen

Collections und Sprachgefühl

  • Die Collection-Typen von Janet gibt es sowohl in veränderlicher als auch in unveränderlicher Form
  • Unveränderliche Collections haben Wertsemantik; daher ist der unveränderliche Vektor [1 2] nicht von (take 2 [1 2 3]) zu unterscheiden, auch wenn die Speicheradressen unterschiedlich sind
  • Veränderliche Collections haben Referenzsemantik; daher ist die Hash-Tabelle @{:x 1 :y 2} nur mit sich selbst gleich, während eine andere Hash-Tabelle mit denselben Schlüsseln und Werten ein separates Objekt ist
  • Die Syntax verwendet zwar viele Klammern, unterscheidet Formen aber durch [] für Listen und {} für Tabellen
  • Veränderliche Literale tragen immer das Präfix @, zum Beispiel @"mutable string"
  • Anonyme Funktionen werden als (fn [x] (+ 1 x)) geschrieben; außerdem gibt es die Kurzschreibweise, einen Ausdruck mit | zu einer Funktion anzuheben, etwa |(+ 1 $)
  • Splat oder Spread wird mit ; ausgedrückt, zum Beispiel (+ ;args)
  • Backtick-Strings können mit einer beliebigen Anzahl von Backticks geöffnet und mit derselben Anzahl wieder geschlossen werden; innerhalb davon werden Escape-Sequenzen wie \n nicht angewendet
  • Restparameter werden mit & statt . geschrieben, zum Beispiel (defn foo [first & rest] ...)
  • Janet unterstützt keine Reader-Makros; die Syntax selbst ist also fest, und wer Janet lesen kann, kann jedes Janet-Programm lesen

Makros und Compile-Time-Zustand

  • Janet-Makros sind Code, der Code schreibt, und behandeln zur Compile-Time gleichzeitig den aktuellen Ausführungsfluss, der Werte und abstrakte Syntaxbäume manipuliert, sowie den zukünftigen Fluss des Anwendungscodes, der später ausgeführt wird
  • Janet-Makros sind nicht hygienisch, und es gibt auch keinen separaten Namespace für Funktionen
  • Allerdings lassen sich Literal-Funktionen per unquote einfügen, sodass vollständig referenztransparente Makros geschrieben werden können
  • Wenn ein Janet-Programm kompiliert wird, werden zunächst Top-Level-Befehle, allgemeine Anweisungen und Funktionsdeklarationen ausgeführt; anschließend wird ein Snapshot des Programmzustands auf die Festplatte geschrieben
  • Dieser Snapshot bewahrt geteilte Referenzen, sodass sich veränderliche Werte auch nach einem Neustart weiter verändern lassen
  • Generatoren merken sich, welcher Befehl bei der nächsten Fortsetzung auszuführen ist, und Closures behalten ebenfalls ihre gebundenen Werte
  • Makros sind eine spezielle Form von Codeausführung zur Compile-Time, aber diese Fähigkeit lässt sich auch ohne Makros nutzen
  • In Spielen können Splines vorab verarbeitet werden; Dateien lassen sich zur Compile-Time einlesen, um Assets in das finale Binary aufzunehmen, und auch beliebige Seiteneffekte sind möglich
  • Janet for Mortals zeigt ein Beispiel, das Datenbank-Bindings auf Basis von SQL-Schemadateien automatisch erzeugt, und bewertet solche Aufgaben in den meisten Sprachen als ziemlich schwierig

Angenehmer als die Lisp-Tradition

  • Janet folgt alten Lisp-Konventionen nicht einfach unverändert
  • CAR heißt first, PROGN heißt do, LAMBDA heißt fn, SETQ heißt def
  • nil ist keine leere Liste, sondern ein eigenständiger Typ, und boolesche Werte sind First-Class-Werte
  • Auf die Familie aus EQ, EQL, EQUAL, EQUALP wird verzichtet, und verkettete Listen tauchen kaum auf

2 Kommentare

 
GN⁺ 2 시간 전
Hacker-News-Kommentare
  • Janet hat einige Schwächen. Vor allem fehlt es bei der Versionsangabe in der Paketverwaltung, und auch insgesamt an Bibliotheken für Dinge wie fortgeschrittenes HTTP-Routing.
    Trotzdem gefällt mir sehr, dass man mit JPM Binärdateien und Skripte bauen kann und dass alles so portabel ist. Ich habe früher sogar einmal als Proof of Concept versucht, die Programmiersprache Janet auf die Playdate-Spielkonsole zu bringen.
    Ich schreibe gern Code in Janet, aber es ist jedes Mal etwas unerquicklich, wenn Leute denken, ich hätte die Sprache entwickelt.

    • Es gibt einen unterhaltsamen Artikel von Julia Evans, in dem sie Gunzip in Julia visualisiert: https://jvns.ca/blog/2013/10/24/day-16-gzip-plus-poetry-equa...
      Eine Version „Janet schreibt Janet“ wäre auch schön.
    • Ich frage mich, ob du jeep schon ausprobiert hast: https://github.com/pyrmont/jeep/
      Es vendort Abhängigkeiten und macht es einfach, moderne Janet-Bundles auch ohne jpm zu installieren.
    • Wenn du serverseitig etwas brauchst, gibt es wie von veqq erwähnt joy, das seinen eigenen leichtgewichtigen HTTP-Server implementiert. Wenn du einen Client brauchst, ist es mit der Janet-C-API ziemlich einfach, libcurl oder andere HTTP-Clients zu wrappen.
      Falls du offen für LLM-Entwicklung bist, kannst du die Wrapper von einem LLM schreiben lassen und die eigentliche Logik in Janet verfassen.
    • Ich frage mich, was mit fortgeschrittenem HTTP-Routing konkret gemeint ist. Für alles rund ums Web nutze ich https://github.com/joy-framework/joy, und wenn wirklich etwas fehlt, könnte ich es vermutlich innerhalb einer Woche einbauen.
  • Es gibt auch Fennel, eine ähnliche Sprache desselben Entwicklers aus früherer Zeit. Sie kompiliert nach Lua, und auch die Implementierung ist komplett in Lua geschrieben.
    Da sie keine eigene Standardbibliothek hat, fehlen viele der guten Dinge aus Janet, etwa die Parser-Bibliothek, aber zum Schreiben von Skripten in Umgebungen mit eingebettetem Lua ist sie gut geeignet.
    https://fennel-lang.org/

    • Fennel ist wirklich gut und auch ein schöner Einstieg in die Clojure-Familie. Meine größte Beschwerde ist, dass Debugging ein typisches Transpile-Minenfeld ist.
      Die Verbindung zwischen Fennel und der Lua-VM ist sehr fragil und erreicht nicht einmal die Hälfte der Qualität von Janet-Debugger und REPL. Fennel ist deutlich portabler und kann dank LuaJIT SBCL sogar klar übertreffen, was das umso bedauerlicher macht.
      Aber ich denke, die Transpile-Erfahrung ist letztlich das, was alles ausbremst. Es gibt Workarounds, aber selbst wenn man debug.setinfo implementiert, stößt man auf unerquicklichere Grenzfälle wie match-Blöcke.
      Ich denke, es hätte großen Wert, LuaJIT2 zu forken und Debugging sowie Fehlerstruktur so zu überarbeiten, dass sie besser zur Sprachtransparenz passen. Dann würden Sprachen wie Fennel deutlich attraktiver wirken.
  • Der Autor hat diese Tools, die früher auch schon auf HN vorgestellt wurden, in Janet gebaut.
    https://bauble.studio
    https://toodle.studio
    Diese beiden interessanten Kunst-Tools haben mich eine Zeit lang ziemlich optimistisch in Bezug auf Janet gemacht.

  • Ich freue mich immer, wenn Janet Aufmerksamkeit bekommt. Als eines der modernen Features würde ich sandbox nennen.
    „Deaktiviert Mengen von Funktionen, damit der Interpreter bestimmte Systemressourcen nicht verwenden kann. Einmal deaktivierte Funktionen können nicht wieder aktiviert werden.“
    https://janet-lang.org/api/misc.html#sandbox

    • Wirklich ein großartiges Feature, aber ich frage mich, in welchen Situationen ein durchschnittlicher Programmierer solches Sandboxing eigentlich braucht.
  • Als ich „SETQ is def“ gesehen habe, habe ich zuerst laut „Was?“ gesagt. SETQ erzeugt schließlich keine Bindung, sondern aktualisiert nur.
    Nachdem ich die Dokumentation gelesen habe (https://janet-lang.org/docs/bindings.html), scheint der Autor tatsächlich falschzuliegen; dort steht, dass „mit def erzeugte Bindungen unveränderlich sind“. Vermutlich war „SETQ is set“ gemeint.
    Janet wirkt auf mich wie ein guter Mittelweg zwischen Guile, Tcl und CL, und ich würde die Sprache wirklich gern mögen, aber ich habe eine instinktive Abneigung gegen eckige Klammer-Vektoren für Lambdas und Kontrollflussoperatoren. Mit Clojure ist es für mich ähnlich schwer, auch wenn ich es mit genug Mühe vielleicht doch überwinden könnte.
    Und ich frage mich auch, wie der aktuelle Stand von LSP/SLIME ist. Das ist heutzutage ziemlich wichtig.

    • Die Verwendung von eckigen Klammern in der Clojure-Syntax ist sehr konsistent und ziemlich logisch.
      Verwendet man runde Klammern, bestimmt das erste Element einer Liste, wie der Rest der Liste interpretiert wird. Zum Beispiel ist (func a b c) ein Funktionsaufruf, (macro x y z) eine Makroerweiterung, und ([p q r] …) ist ein „nackter“ Funktionskörper, der mit einem Parametervektor beginnt und dem Ausdrücke zur Ausführung folgen.
      Eckige Klammern verwendet man, wenn die Elemente alle vom gleichen „Typ“ sind und das erste Element keine Sonderrolle hat. Zum Beispiel ist (defn f [a b c] …) eine Sammlung gleichartiger Parameter, bei der der erste Parameter nichts Besonderes ist, und (let [a 1 b 2] …) ist ebenso eine Sammlung von Bindungen, bei der die erste Bindung keine Sonderrolle hat.
      Die einzige Ausnahme, die mir einfällt, ist case, wenn mehrere Matching-Elemente gruppiert werden; das dient aber der Bequemlichkeit. Als ich diese Logik verstanden habe, hat sich meine Meinung geändert, und seitdem finde ich es schön.
    • Man muss eckige Klammern und geschweifte Klammern einfach gar nicht verwenden. Statt [1 2 3] kann man (array 1 2 3) schreiben, und statt (fn [x] (+ 1 x)) eben (f (x) (+ 1 x)).
      Sie sind nicht zwingend.
    • Wenn man versteht, wie Destructuring in Clojure funktioniert, wird klar, welche Rolle die eckigen Klammern spielen.
  • In Systemskripten ab einer gewissen Länge ersetzt Janet für mich sh, Python, awk usw.
    Die Startzeit für die Ausführung von Skripten ist sehr schnell und liegt auf meinem System laut hyperfine bei 1,4 ms, also ähnlich wie die 1 ms von dash. Gemeint sind Skripte, nicht kompilierte Binärdateien.
    Dank des Moduls sh-dsl kann man Shell-Befehle sehr elegant so schreiben wie ($ cmda w x | cmdb y z). Auch die Möglichkeit, für das Debugging ein Image zu laden, ist eine große Hilfe.
    Ich benutze es erst seit Kurzem, aber es scheint schon jetzt eine meiner Lieblingssprachen zu werden, und das einzige andere Lisp, das ich zuvor benutzt habe, war MIT Scheme für SICP.

    • Für mich hat babashka sh, Python, awk usw. ersetzt.
  • Dieser Beitrag wirkt erfrischend. Er riecht nach einer Diskussion aus der Zeit vor der AI-Ära im Internet.
    Es gibt eine neue Sprache, eine neue Syntax und hitzige Debatten zwischen Leuten, die seit Jahren Code schreiben. Es wäre schön, wenn jemand eine Online-Community starten würde, in der AI nicht erlaubt ist.

    • Falls du die jüngsten Entwicklungen nicht verfolgt hast: Der neueste Relaunch von digg.com ist gescheitert, weil er den Ansturm von Bots nicht bewältigen konnte.
      Eigentlich müsste man wohl vom vorletzten Relaunch sprechen, und inzwischen scheint es schon wieder eine neue Homepage zu geben. Wer als Erster einen verlässlichen Weg findet, AI in Online-Communities zu verhindern, wird wahrscheinlich sehr reich werden.
      https://www.techspot.com/news/111698-digg-relaunch-fails-two...
    • Ich denke oft darüber nach, wie man eine Online-Community ohne erlaubte AI aufbauen könnte. Besonders schwierig ist es, das zu schaffen, ohne die Anonymität im Netz zu zerstören.
      Eine Art „Nachweis der Menschlichkeit“ ist ein schwer zu lösendes Problem.
    • Das Erstaunliche an AI ist, dass man kein begeisterter AI-Befürworter sein muss, um AI in ein Gespräch hineinzubringen, das gar nichts mit AI zu tun hat. Die Gegner erledigen das stattdessen.
    • So ein Ort wäre vermutlich lobsters. Nach einer Diskussion mit über 300 Kommentaren, wahrscheinlich der größten in der Geschichte der Seite, wurden AI-Texte verboten.
      Die genaue Regel der Moderation lautete zwar „bedeutungsvolle menschliche Urheberschaft“, aber davon sollte man sich nicht täuschen lassen. Auf lobsters gibt es viele Menschen, die LLMs ideologisch ablehnen. Wie „bedeutungsvoll“ die Technik eingesetzt wurde, spielt kaum eine Rolle.
      Meine Arbeit wurde allein deshalb als Müll eingestuft, weil AI sie berührt hatte, und manche nannten mich, nachdem ich gesagt hatte, dass ich AI benutze, einen Exhibitionisten oder Fetischisten. Das sollte man wissen, wenn man überlegt, sich dort anzumelden.
    • Ironischerweise geht es in diesem Top-Kommentar jetzt selbst um AI.
  • Bei Sätzen wie „Indem man Literalfunktionen unquoten kann, ermöglicht Janet vollständig referenztransparente Makros“ scheinen Lisp-Leute sich wirklich für sehr abstrakte Dinge zu begeistern.
    Wenn man das einer gewöhnlichen Person auf der Straße sagt, würde sie wahrscheinlich weglaufen.

    • Ein Beispiel für ein C-Makro mit Literalen, aber ohne Referenztransparenz, wäre dieses hier:
      #define MULTIPLY(x, y) x * y
      int result = MULTIPLY(2 + 3, 4); // 14
      Nur weil man nicht weiß, was ein Begriff bedeutet, ist er nicht schlecht. Dem Wortlaut nach war das vermutlich so gemeint.
      Es ist gut, eine gemeinsame Sprache für Muster und Probleme zu haben, die in der Programmierung immer wieder auftauchen. Sich über Fachbegriffe lustig zu machen nach dem Motto „Diese Gruppe von Programmierern ist aber seltsam“ ist sinnlos und wirkt eher kontraproduktiv.
    • Ich frage mich, ob du jemals versucht hast, einer gewöhnlichen Person auf der Straße objektorientierte Programmiersprachen und ihre Vorteile zu erklären.
    • Vor etwa einem Jahr habe ich angefangen, einen Scheme-Interpreter zu schreiben, und bin damit ziemlich weit gekommen. Vor ein paar Monaten habe ich damit aufgehört, als ich einen neuen Job bekam.
      Ich überlege, wieder damit anzufangen, frage mich aber, ob Nischenfeatures die Implementierungsarbeit überhaupt wert sind. Für mich sind sie auch schwierig umzusetzen. Vielleicht wäre es besser, dynamic-unwind zu überspringen und vielleicht auch call/cc wegzulassen und mich stattdessen auf Debuggbarkeit, Ökosystem, Performance und Paketverwaltung zu konzentrieren.
    • Diese Reaktion bekomme ich im Grunde jedes Mal, wenn mich jemand fragt: „Was machen Sie beruflich?“
      Deshalb antworte ich sehr vage mit etwas wie „Ich arbeite mit Computern“ oder sage „Es ist eigentlich nichts besonders Interessantes“ und wechsle das Thema. Sobald ich ein wenig konkreter werde, suchen die Leute nach dem Ausgang.
    • Das gilt vermutlich sogar für durchschnittliche Programmierer.
      Ehrlich gesagt glaube ich, dass Lisp-Communities gerade deshalb profitiert haben, weil sie klein geblieben sind. Zum Beispiel hat selbst das uralte Design Patterns schon davor gewarnt, Komposition der Vererbung vorzuziehen, und trotzdem haben objektorientierte Programmierer weiter Hierarchien mit 15 Ebenen Tiefe gebaut.
  • Als ich Janet zum ersten Mal entdeckt habe, waren diese Dokumente wirklich hilfreich:
    https://janetdocs.org/tutorials
    https://janet.guide/ vom Autor des Beitrags erstellt.

  • Ich fühlte mich von den gelegentlichen Janet-Beiträgen auf HN angezogen, aber Janet for Mortals, das von allen so gelobt wird, fühlte sich für mich überhaupt nicht wie ein Buch für Sterbliche an.

    • Es gibt auch sanfteres Einstiegsmaterial: https://janetdocs.org/tutorials
    • Überraschend. Diese Sprache ist sehr intuitiv und einfach, und es gibt nur sehr wenige Regeln, die man sich merken muss. Es ist zwar ein Lisp, aber die Oberfläche ist sehr klein.
      Verglichen mit anderen Sprachen ist Janet wirklich leicht zu lernen, deshalb überrascht es mich, dass dieses Buch schwierig sein soll. Ich habe das Buch nicht gelesen, kenne die Sprache aber einigermaßen und kann ehrlich gesagt nur Gutes darüber sagen.
    • Für mich persönlich ist die Makro-Syntax zu früh im Buch dran und bremst mich aus, aber danach gibt es wirklich viel Wertvolles darin.
    • So ging es mir mit Haskell. Haskell ist mir zu schwer, aber die Syntax selbst gefällt mir.
      Janet wirkt wie Lisp 2.0, also ist auch die Syntax Lisp-artig.
 
GN⁺ 2 시간 전
Meinungen auf Lobste.rs
  • Nach nur 10 Monaten mit Janet war ich so tief drin, dass ich fast alles außer Sprachen aus der APL-Familie vergessen hatte, und während ich die Community-Dokuseite betreibe, schreibe ich auch ein Tutorial
    Innerhalb der ersten 3 Wochen habe ich alle meine persönlichen Skripte neu geschrieben, und auch neue Betriebssoftware, die ich baue, schreibe ich in Janet
    Implementierungsseitig funktioniert bei Janet fast die ganze Sprache wie eine Hash-Map: Mit (keys (curenv)) kann man lokale Symbole sehen, mit (keys (getproto (curenv))) die Core-Symbole, und wenn man will, kann man auf Hash-Map-Basis sogar etwas CLOS-Ähnliches bauen; eine Implementierung gibt es auch
    Mit dem Joy Web Framework betreibe ich ungefähr 20 Websites und mehrere Services auf einem einzigen kostenlosen VPS mit 512 MB, und dazu habe ich auch ein Tutorial geschrieben
    Allerdings ist die Bezeichnung „unveränderliche Collections“ etwas ungenau; die Standardbibliothek gibt meist veränderliche Werte zurück, daher gibt es aktuell keinen großen Grund, auf Unveränderlichkeit zu bestehen
    Besonders stark war die Funktion, Werte aus der Compile-Zeit in die Laufzeit zu übergeben. Wenn man zum Beispiel eine biblische .tsv beim Kompilieren als Hash-Map in das Binärprogramm einbettet, muss zur Laufzeit nur noch nachgeschlagen werden, und das war sogar doppelt so schnell wie eine Go-Version mit embed
    Wenn man dasselbe in Go direkt als Hash-Map implementiert, wird der Code viel länger, aber in Janet konnte ich sogar einen Lisp-nach-Go-Compiler in 46 Zeilen bauen
    Der interessantere Punkt, den Ian Henry erwähnt hat, ist, dass Janet den Status von Closures über Images/Sessions hinweg bewahrt: Wenn man die relevante Umgebung in der (curenv)-Hash-Map speichert und sie in einer neuen REPL-Session wiederherstellt, bleibt auch der interne Zustand der Closure erhalten

    • Ein cooles Beispiel für etwas, das mit Janet gebaut wurde, ist https://bauble.studio, und einen Artikel über den Entstehungsprozess gibt es unter https://ianthehenry.com/posts/bauble/building-bauble/. Der Einsatz von WASM fällt besonders auf
      Es gibt auch das Lisp-basierte Musik-DSL https://lisp.trane.studio/, dazu das Paper https://dl.acm.org/doi/abs/10.1145/3677996.3678285 und ein sehenswertes Ergebnisbeispiel unter https://x.com/greg_ash/status/1824218993118388708
      Ich habe auch selbst eine Bibliothek gebaut, die eine SQL-ähnliche Abfragesyntax über verschiedene Datenstrukturen hinweg bereitstellt
      Sie unterstützt das Einfügen und Aktualisieren von DataFrames sowie das Speichern/Laden von CSV und enthält außerdem Datalog und miniKanren; vektorisierte Operationen wie in APL sind ebenfalls möglich
      Es gibt auch jnj, mit dem man J direkt in Janet verwenden kann, und im Joy Web Framework gibt es ein DB-Abfrage-DSL mit Formen wie (var account (db/find-by :account :where {:login (auth-result :login)})), das auch im echten Authentifizierungscode einer Website verwendet wird
    • Im Original war die Formulierung „unveränderliche Collections“ wohl unpräzise. Gemeint waren eher zusammengesetzte Werttypen und Referenztypen
      Bei „unveränderliche Collections“ denkt man an persistente Datenstrukturen, und auch wenn die nützlich sind, gehören sie nicht zu Janets Grundfunktionalität
      Was mir tatsächlich gefällt, ist die Symmetrie zwischen Werttypen und Referenztypen, und obwohl am Ende des Artikels „immutable composite values“ stand, hätte ich die Bedeutung wohl auch nicht sofort verstanden, wenn ich es nicht selbst geschrieben hätte
  • Janet wirkt frisch und ist eine einbettbare Sprache, daher würde ich sie gern einmal für eingebettetes Scripting in Projekten wie Game Engines ausprobieren
    Sie scheint gut für Einsatzbereiche zu passen, in denen Hot Reload für schnelle Iteration ohne DLL-Austausch nötig ist; Lua ist ebenfalls großartig, aber Janet wirkt in mancher Hinsicht ausdrucksstärker

  • Janet ist als Sprache wirklich großartig, und ich würde sie irgendwann gern als Skriptsprache in einem Zig-Projekt einsetzen. Es freut mich, dass mehr Leute Janet erwähnen

  • Es sieht gut aus, aber ich habe mich mit babashka bereits an Clojure-Scripting gewöhnt, deshalb fühlt es sich ähnlich an. Ich frage mich, ob ich außer der Einbettbarkeit noch einen großen Vorteil übersehe
    Dinge wie „Array-Destrukturierung mit Rest-Argumenten kann potenziell teure Kopien verursachen“ gefallen mir nicht, weil es insgesamt weniger funktional wirkt

    • Eines der Killer-Features von Janet ist meiner Meinung nach die eingebaute PEG-Unterstützung. Beim Bauen eines Textbox-DSLs für ein Game-Dev-Nebenprojekt war das wirklich praktisch
      Das ist eine Funktion, die mir fehlt, sobald ich in einer anderen Sprache Text parsen muss
    • Solche Destrukturierung ist keine häufig genutzte Vorgehensweise, und Janet-Arrays/Tupel sind keine verketteten Listen
      Janet ist weniger ein kleines, einbettbares Clojure als vielmehr Lua mit besserer Unterstützung für funktionale Programmierung