3 Punkte von GN⁺ 2024-05-03 | 1 Kommentare | Auf WhatsApp teilen
  • Cognition ist ein Sprachforschungsprojekt, das vollständige postfixe Antisyntax wählt, um das Read-ahead-Problem von Lisp und konkatenativen Sprachen zu vermeiden
  • Die zentralen Mechanismen delimiter, ignore, singlet, falias, crank und metacrank erlauben es Programmen, ihre eigenen Tokenisierungsregeln und Ausführungszyklen zu ändern
  • Das Bootstrap startet in einem Zustand, in dem jedes Zeichen als einzelnes Token gelesen wird, und bewegt sich selbst in eine Umgebung, die Leerzeichen und Zeilenumbrüche als Trennzeichen verwendet
  • crank und metacrank steuern, wann Tokens ausgewertet und wann sie gesammelt werden, sodass sich Prefix-Syntax wie #-Kommentare, \-Escape, [-Quote und (-Macro innerhalb eines postfixen Systems definieren lässt
  • Auch ein Brainfuck-Dialekt wird nicht über einen separaten Parser, sondern über Cognition-Wörter und Tokenisierungsregeln implementiert und zeigt damit eine Richtung, in der Syntax selbst zu Code gemacht und automatisiert wird

Wo Cognition an bestehender Syntax ansetzt

  • Lisp bietet mit S-Expressions und seinem Makrosystem mächtige Metaprogrammierung, bleibt aber weiterhin vom Einfluss einer festen Syntax geprägt
    • Eine öffnende Klammer signalisiert, dass bis zur schließenden Klammer weitergelesen werden muss; deshalb ist es schwierig oder in manchen Implementierungen unmöglich, die Rolle von Klammern innerhalb der Sprache zu verändern
    • Wenn man nachträglich ändern will, wie bereits gelesene Tokens getrennt wurden, ist viel String-Verarbeitung nötig
  • Der Prozess, bei dem auf Basis der aktuellen Eingabe entschieden wird, ob weiter vorausgelesen werden muss, ist Syntax; sobald standardmäßig Read-ahead angenommen wird, ist man an bestimmte Syntaxformen gebunden
  • Cognition vermeidet das durch eine vollständig postfixe Antisyntax
    • Es ähnelt konkatenativen Sprachen, sieht aber auch bei typischen konkatenativen Sprachen wegen eckiger Klammern oder Quote-Zeichen für Strings ein Read-ahead-Problem
    • Das Makrosystem von Racket wird davon abgegrenzt, weil es Vorverarbeitung nutzt statt dynamischer Syntaxänderung zur Laufzeit

Projekt und Grundidee

  • Cognition ist ein aktives Forschungsprojekt, das über mehrere Monate gemeinsam mit Matthew Hinton durchgeführt wurde
  • Das Implementierungs-Repository liegt unter cognition-rust; im Repository befindet sich auch ein Paper zur Sprache
  • Hintergrundwissen zu Parsing, Tokenisierung und Syntax hilft beim Verständnis
  • Die Erklärung beginnt bei „baremetal cognition“-Code und verfolgt, wie dieser sich zu einer Syntax ähnlich Stem entwickelt

Baremetal Cognition und Tokenisierung

  • Baremetal Cognition sieht äußerlich Brainfuck ähnlich, kann aber deutlich stärkere Metaprogrammierung leisten
  • Der sehr kleine Bootstrap-Code nutzt sogar Leerzeichen und Zeilenumbrüche bedeutungsvoll; im Anfangszustand wird jedes einzelne Zeichen als Token gelesen
  • Cognition ist grundsätzlich stackbasiert entworfen, verwendet aber den Begriff container in einem allgemeineren Sinn als Stack
  • In der Basisumgebung wird außer einem speziellen falias kein Wort automatisch ausgeführt
  • delimiter, ignore, singlet

    • delimiter erlaubt dem Tokenizer zu erkennen, wo ein Token endet und das nächste beginnt
    • Die Liste der einstelligen delimiter kann innerhalb von Cognition-Code geändert und gelesen werden
    • ignore-Zeichen werden zu Beginn der Tokensammlung in jedem Read-Eval-Print-Loop übersprungen
    • Der Standardzustand ist: alle Zeichen sind delimiter, es gibt keine ignore-Zeichen
    • Die Listen delimiter, singlet und ignore können ihr Verhalten über Whitelist-/Blacklist-Flags ändern
    • Die Grundeinstellung ist: keine blacklist delimiter, keine whitelisted singlets, keine whitelisted ignore-Zeichen
    • singlet ist eine dritte Tokenisierungskategorie, die sich selbst in das Token aufnimmt und danach die Tokensammlung beendet
  • falias

    • falias ist eine Liste von Wörtern, die sofort ausgeführt werden, sobald sie in den container gelangen
    • Das Standard-falias f wird nicht im container abgelegt, sondern führt das oberste Wort im container aus
    • Wenn im Beispiel f das Wort d ausführt, ändert d die delimiter-Liste auf den String-Wert eines Wortes
    • Danach folgt ein Bootstrap, der Zeichen wie l, g, t und d schrittweise zu non-delimiters macht und Leerzeichen sowie Zeilenumbrüche zu delimiter und ignore umstellt

Die vom Bootstrap erzeugte Ausführungsumgebung

  • Das anfängliche Bootstrap ändert delimiter- und ignore-Regeln und erzeugt schließlich eine Umgebung, in der Leerzeichen und Zeilenumbrüche Token-delimiter sind und am Beginn eines Tokens übersprungen werden
  • Danach werden 1 und crank gelesen, und f führt crank aus, wodurch die Umgebung crank 1 betreten wird
  • Der Kern dieses Vorgangs ist, dass sich die Tokenisierung während der Ausführung ändern lässt
    • Änderungen an delimiter, singlet und ignore lassen sich als Programm automatisieren
    • Weil der Ansatz postfix ist und kein Read-ahead nutzt, muss vor der Auswertung eines Ausdrucks nicht erst ein oder mehrere Tokens vorausgeparst werden
  • falias ermöglicht die Ausführung bestimmter Wörter auch ohne Prefix-Wörter oder automatische Ausführung von Basiswörtern

crank und metacrank

  • crank ist ein Mechanismus, der festlegt, in welchem Zyklus Tokens auf dem Stack ausgeführt werden
  • Das Wort crank nimmt eine Zahl als Argument und führt danach für jedes n-te Wort, das in den container gelangt, den Stack-Top aus
    • 1 crank am Ende des Bootstraps erzeugt eine Umgebung, in der alle Tokens ausgewertet werden
    • Im Zustand 5 crank können Wörter gesammelt werden, bis das fünfte Token eintrifft
  • Der Beispielcode verwendet unglue, swap, quote, prepose und def, um ein Wort namens 2crank zu erstellen
    • unglue holt den Wert eines Wortes und kann auch Funktionszeiger von Builtins wie crank holen
    • prepose ähnelt compose in Stem, fügt aber vorn an und legt in VMACRO ab
    • def definiert 2crank so, dass es 2 auf den Stack legt und das Builtin crank aufruft
  • Container und Macro in Cognition

    • In Stem können Wörter direkt auf den Stack gelegt werden; in Cognition landen nicht ausgewertete Wörter in einem container
    • Durch dieses Design können Wörter wie compose einen Ein-Wort-container und andere container über eine einheitliche API behandeln
    • Macros in Cognition unterscheiden sich von Stem-quotes
    • Wenn ein Macro ausgewertet wird, ignoriert es crank und alle inneren Elemente werden ausgewertet
    • Wird ein an ein Wort gebundenes Macro ausgewertet, läuft das gesamte Macro unabhängig von crank, und der cranker wird nur einmal erhöht
    • Macros sind nützlich für crank-unabhängigen Code und für Expansionen zu Optimierungszwecken
  • metacrank

    • n m metacrank setzt für das n Elemente tiefer liegende Element auf dem Stack eine Auswertung mit Periode m
    • crank ist identisch mit 0 m metacrank
    • Pro Token kann nur ein metacrank ausgewertet werden, wobei der niedrigere metacrank Vorrang hat
    • metacrank und crank gelten nicht nur für Tokens aus Dateien, sondern auch für die rekursive Auswertung von Wortdefinitionen
    • metacrank ermöglicht direkte Syntaxmanipulation wie „Ich möchte nach dem Lesen von n Tokens dieses Token ausführen“
    • Programmierte Prefix-Wörter können später mit undef entfernt werden, wenn sie nicht mehr gebraucht werden
    • Auch Prefix-Zeichen, die nicht bei einem bestimmten Abschlusszeichen, sondern nach einer bestimmten Anzahl von Tokens stoppen, lassen sich erzeugen
    • Nutzereingaben können in ein Mathematikprogramm gegeben und dessen Ausgaben an ein Syntaxsystem wie metacrank weitergereicht werden

Entwicklung zu einem Stem-Dialekt

  • Nach dem Bootstrap baut Cognition innerhalb der Sprache schrittweise eine Syntax auf, die Stem v2 ähnelt
  • Zuerst wird f aus der falias-Liste entfernt, sodass nur ing übrig bleibt
    • Wenn man f direkt auf den Stack legt, wird es ausgeführt; deshalb wird zunächst ff erzeugt und der String halbiert, um zwei f zu erhalten
    • Danach wird f als leeres Wort definiert, das false entspricht
  • #-Kommentare

    • Das Zeichen # ist das erste Codebeispiel, das wie ein echter Prefix funktioniert
    • Dieses Kommentarzeichen wirkt als Prefix, der Text bis zum newline verwirft, und erzeugt damit eine Syntax, bei der der Parser vorausliest
    • Die Implementierung kombiniert geti, getd, gets, crankbase, halt, VMACRO cast, singlet, delim und weitere
    • geti, getd und gets holen ignore, delimiter beziehungsweise singlet als Strings
    • halt setzt alle metacranks auf 0
    • VMACRO cast wandelt den container am Stack-Top in ein Macro um
    • Die Definition von # ändert die Tokenisierungsregeln, ruft # für ein künftig zu tokenisierendes Wort auf, droppt diesen Kommentar und kehrt dann zum ursprünglichen crank und metacrank zurück
  • escape, quote, macro

    • \ wird als Escape-Zeichen definiert, das erlaubt, auch ein sonst auszuwertendes Wort auf den Stack zu legen
    • Danach wird eine [-Quote-Definition hinzugefügt; anschließend definiert sie sich mithilfe dieses Quotes erneut zu einer besseren [-Definition, die rekursives Quoting erlaubt
    • Wegen des postfixen def kann die alte Definition verwendet werden, um die neue zu bauen
    • Dieses Muster ist eine häufige Entwicklungsweise in Low-Level-Cognition
    • ( wird als Macro-Klammer definiert
    • Macros werden so angelegt, dass sie automatisch expandieren; es gilt als effizienter, ein bereits expandiertes Macro an ein Wort zu binden
    • Funktional werden sie auf dieselbe Weise ausgewertet
    • expand expandiert Wortdefinitionen innerhalb von quotes oder Macros rekursiv mit unglue
    • Zuerst wird ein einfaches expand definiert, danach wird expand mithilfe seiner selbst so neu definiert, dass es allgemeinere Fälle behandelt

Brainfuck-Dialekt

  • Cognition definiert auf dem entwickelten Stem-Dialekt einen Brainfuck-Dialekt
  • Ein Ausführungsbeispiel ist ../crank -s 2 bootstrap.cog helloworld.bf brainfuck.cog
  • brainfuck.cog ist kein Brainfuck-Parser im üblichen Sinn
    • Es definiert Brainfuck-Wörter
    • Es tokenisiert Brainfuck
    • Es führt es in der nativen Cognition-Umgebung aus
  • Dieses Beispiel zeigt, dass sich alternative Syntaxen mit Cognition-Syntax leicht definieren lassen
  • Statt Symbole zu lesen und abhängig vom Symbol eine Aktion zu wählen, definiert Cognition die Prefix-Zeichen selbst als Wörter, die metacrank verwenden, und legt die Syntax damit in Wortdefinitionen

Idee eines dialect dialect

  • Man kann sich Wörter wie mkprefix vorstellen
    • Zum Beispiel ein Wort, das zwei Eingabewörter [ und ] sowie eine Operation entgegennimmt und automatisch definiert, dass [ diese Operation anwendet, bis ] erreicht wird
  • Solche Ideen sind möglich, weil sowohl metacrank als auch def gewöhnliche Wörter sind
  • Da alles, einschließlich d, i und s, ein Wort ist, lässt sich ein abstrakterer Dialekt bauen, der den Prozess der Syntaximplementierung automatisiert
  • In der Standardbibliothek ist das noch nicht implementiert, es gibt aber Punkte, die mit Matthew Hinton als mögliche Standardbibliothek diskutiert wurden
    • Ein metaword, das abstrakte Wörter automatisch erzeugt und aufruft
    • Eine word-generator-Suche, die die aktuelle wordlist automatisch abstrahiert
    • Eine Methode, ein Abstraktionsframework zur Problemlösung anzuleiten

Möglichkeiten, Syntax als Code zu behandeln

  • In Cognition entspricht String-Verarbeitung der Nachbearbeitung des Tokenizers, wodurch String-Operationen eine starke Bedeutung erhalten
  • Als potenzielle Anwendungsfelder werden Symbolic AI, Forschung zu Syntax und Grammatik sowie Experimente mit Prototypen für Sprachen und Metalanguages genannt
  • Es gibt auch Ideen wie Programme zum Lesen von Konfigurationsdateien, eine Cognition-basierte Shell oder ein Cognition-basiertes Betriebssystem
  • Der Kern ist, dass Cognition „syntax as code“ möglich macht
    • Syntax lässt sich dynamisch programmieren
    • Die Erzeugung von Syntax selbst lässt sich automatisieren
  • Konzepte wie Metastack und cd wurden nicht behandelt und bleiben Themen, die in einem Folgebeitrag aufgegriffen werden könnten

1 Kommentare

 
GN⁺ 2024-05-03
Hacker-News-Kommentare
  • Ich bin noch nicht überzeugt, dass dieser Ansatz besser ist als Rackets Konfiguration der Reader-Ebene
    In Racket kann man zum Beispiel eine eingebaute Datalog-Implementierung erstellen, die Datalog-Syntax verwendet und trotzdem mit anderen Racket-Modulen interoperabel ist, ohne das zugrunde liegende Datenmodell zu verändern
    Man kann also Metaprogrammierung betreiben, ohne in S-Ausdrücke eingesperrt zu sein, und das Ganze trotzdem auf einer höheren Ebene behandeln
    Diese Art von Syntax-Bootstrapping ist cool und wissenschaftlich wertvoll, aber ich weiß nicht, ob sie grundlegend besser ist als der Racket-Ansatz
    Lisp-, Scheme- und Racket-Makros arbeiten normalerweise auf dem AST, aber Rhombus arbeitet auf etwas AST-Ähnlichem namens "shrubbery", das einige Parsing-Entscheidungen auf später verschiebt und dadurch etwas Flexibilität für Syntax-Erweiterungen bietet
    Siehe: https://docs.racket-lang.org/guide/hash-reader.html, https://docs.racket-lang.org/datalog/datalog.html, Rhombus-Paper https://doi.org/10.1145/3580417
    • Ich bin auch nicht sicher, ob das besser ist als Common Lisps readtable, und ich halte Rackets #lang für benutzerfreundlicher als CL-readtables
      Readtables allein sind mächtig genug, um damit einen C-Compiler zu implementieren: https://github.com/vsedach/Vacietis
    • Dass als Standardbeispiel Brainfuck verwendet wird, lässt mich daran zweifeln, ob das wirklich ernst gemeint ist
      Persönlich musste ich laut lachen, als "metacrank" auftauchte
    • Die Aussage, Lisp-Makros arbeiteten auf einem AST, trifft auf Lisp nicht zu
      In Emacs Lisp, Common Lisp und ISLISP nehmen Makros einfach beliebige Daten entgegen und geben beliebige Daten zurück; ein Konzept wie ein AST gibt es dort nicht
      Wenn man (foo-macro ...) aufruft, kann ... beliebige Daten enthalten
      Zum Beispiel nimmt (defmacro rev (&rest items) (reverse items)) einfach die Quellargumentliste des Makroaufrufs entgegen und kehrt sie um
      Man kann es etwa als (rev 1 2 3 4 +) oder (rev (rev 10 n -) (+ a 20 b) (rev 30 a *) list) schreiben, und tatsächlich werden Listen, Zahlen und Symbole übergeben
      Das ist weder Text noch AST, und es funktioniert genauso, wenn man berechnete Daten an eval übergibt
      Lisps Reader liest im Grunde die Datenebene der symbolischen Ausdrücke, und EVAL, Makros und andere Funktionen arbeiten hauptsächlich auf Daten
      Der Compiler kann intern natürlich eine AST-Darstellung erzeugen, aber das ist Implementierungsfreiheit; Lisp-Sprachen sind normalerweise über eine Datengrammatik definiert, nicht über eine Textgrammatik
      Ein Lisp-Interpreter ist ein "List Processor", der zur Laufzeit S-Ausdrücke statt Text verarbeitet, und auch COMPILE nimmt S-Ausdrücke statt Text entgegen
      Racket und Scheme haben ein separates Makrosystem
  • Ein Rat an den Autor: Wenn das Wichtigste zuerst kommt, wirkt der Text viel solider
    Es dauert mehr als 300 Wörter, bis das eigentliche Projekt Cognition überhaupt erwähnt wird, und so interessant die Lisp-Diskussion auch ist, ich bezweifle, dass sie das Wichtigste am Projekt ist
    Wenn ich einen informativen Text lese, frage ich mich ständig: "Ist das meine Zeit wert?" Deshalb sollte das Dokument von Anfang an klar machen, worum es geht
    Ein Satz wie "Cognition ist eine neue Sprache, die benutzerveränderbare Syntax erforscht" hätte schon gereicht, aber selbst nach den ersten vier Absätzen war schwer zu beurteilen, ob es sich lohnt weiterzulesen
    • Ich werde diese Sprache wahrscheinlich ohnehin nicht benutzen, und selbst wenn doch, würde ich die Informationen eher aus der Dokumentation als aus diesem Artikel holen
      Wenn Zeit Geld ist, dann war die Zeit für das Lesen dieses Textes verschwendet
      Statt zu erwarten, dass alle Inhalte im Internet dem persönlichen Geschmack angepasst sind, sollte man sich lieber an bestehende Formate anpassen
      Text ist kein Medium, das wie Video nur sequenziell konsumiert werden muss; man kann diagonal darüber hinweglesen, interessante Stellen suchen und es weglegen, wenn nichts dabei ist, oder zum Anfang zurückkehren, wenn doch
      Unterschiedliche Schreibweisen sind besser, weil sie dazu zwingen, die aufgenommenen Informationen bewusst zu filtern; rein passiver Konsum macht den Kopf träge
      Bei einem Video würde ich allerdings zustimmen
      Bei Videos muss man vor dem Ansehen entscheiden, ob man die Zeit investieren will, und 2x-Geschwindigkeit oder Sprünge von 5–10 Sekunden helfen nur ein wenig, lösen das Problem aber nicht
    • Die Reihenfolge wirkte auf mich ziemlich vernünftig
      Erst wird das Problem erklärt, dann die Lösung vorgestellt
      Schon nach ein paar Sätzen war klar, dass es sich um eine donquijoteske Lösung für ein "Problem" handelt, das 99,999 % der Leute nicht interessiert, mich eingeschlossen, der zwar von Lisp gehört hat, es aber nie außerhalb von Emacs-Konfigurationsdateien benutzt hat, aber ich habe trotzdem einfach weitergelesen
    • Der Lisp-Teil ist zwar nicht das wichtigste Element des Projekts, zeigt aber klar, welche Art von Problem das Projekt lösen will
      Ohne diesen Abschnitt wäre der spätere Teil schwerer zu verstehen gewesen
    • Ich interessiere mich für das Konzept, aber ich hatte Sorge, den Kontext zu verpassen, weil der erste Satz die Notwendigkeit als Reaktion auf Lisps S-Ausdrucks-Syntax zu begründen scheint
      Ohne diesen Hintergrund kann einem der Kontext des ganzen Artikels entgehen, und es ist auch schwer zu beurteilen, ob das ein Strohmannargument ist
      Dadurch wirkt das Ganze, als existiere es nur für einen sehr engen Bedarf, während der Titel viel allgemeiner und als ziemlich interessantes Konzept erscheint
    • Ich finde den Artikel in seiner jetzigen Form völlig in Ordnung
      Schon in den ersten zwei Sätzen wird deutlich, welches Problem gelöst werden soll, und das ist viel hilfreicher als die vorgeschlagene Einleitung, um mein Interesse einzuschätzen
  • Interessanter Artikel, und ich hoffe, die Autoren lassen sich vom Spott hier nicht beirren und setzen ihre dunklen magischen Rituale fort
    Persönlich ist Forth ungefähr die Grenze an philosophischer Reinheit, die ich noch verkrafte, wenn ich die Leiter der Programmierreinheit hinaufschaue
    • Als Verfasser dieses Artikels: Der Spott stört mich nicht, ich finde ihn eher ziemlich lustig und begrüße ihn sogar
      Ich werde mich auch künftig mit mehr dunkler Magie beschäftigen
  • Metaprogrammierung und Programmierung sind dasselbe
    Nur gehen fast alle Sprachen, einschließlich aller Lisps, mit Quoting falsch um, und ausgerechnet m4 ist die Ausnahme

Lisp umgeht dieses Problem mit Makros, indem es erlaubt, metasprachliche Ausdrücke, die als Sätze der Objektsprache formuliert sind, zu behandeln, ohne Zitate zu beachten
Das Problem entsteht dadurch, dass in Objekt- und Metasprache Leerraum als Ende eines Atoms behandelt wird, ohne zwischen beiden zu unterscheiden
COGNITIONs Ansatz einer vollständig postfixen Antisyntax ähnelt konkatenativen Programmiersprachen, aber postfixe Sprachen sind das Dual von präfixen Sprachen und leiden unter demselben Problem
Man muss entweder die Stelligkeit aller Symbole im Voraus festlegen und keine Higher-Order-Funktionen verwenden, oder man braucht ein Paar von Trennzeichen, mit dem sich Bäume serialisieren lassen
Sich auf einen impliziten Null-Stack zu verlassen, ist ungefähr so, als würde man zur Heilung einer Depression eine Lobotomie durchführen

  • Danke für das Feedback, aber wenn du den ganzen Artikel noch nicht gelesen hast, wäre es gut, das zuerst zu tun
    Wir wissen selbst nicht genau, wie viel davon wirklich neu ist, und wenn du meinst, dass man mit Lisp das tun kann, was wir tun, kannst du gern beweisen, dass wir falschliegen
  • Mich würde ein Beispiel interessieren, wie sich Quoting in Lisp und m4 unterscheidet
    Die Behauptung an sich ist interessant, aber es braucht etwas Konkreteres
  • Die Metapher für den impliziten Stack ist zwar flamboyant, aber implizite Stacks gibt es schon seit den frühen Computern und Taschenrechnern
    So wie eine Lobotomie die Fähigkeit zu höherer Verarbeitung verringert, kann man es ähnlich sehen, zum primitivsten Modus der Auswertung von Befehlszeichenketten zurückzukehren
    https://www.hpmuseum.org/rpnvers.htm
  • Ich finde es wirklich schön, dass Cognition während der Ausführung grammatische Strukturen definieren und neu definieren sowie in sie hinein- und aus ihnen herausspringen kann
    Besonders gefällt mir, dass dieser Mechanismus sehr klein ist
    Ich bin kein Sprachexperte und weiß nicht, ob daran wirklich etwas neu ist, aber beim Lesen des Artikels hatte ich durchgehend das Gefühl, die Autoren würden jedes Mal, wenn sie über einen Hügel kommen, ein neues Gebirge von Möglichkeiten entdecken
    Wenn ich es richtig verstanden habe, heißt das, dass man mit Cognition tatsächlich denkende Maschinen bauen kann
    Ein Programm müsste nicht angehalten und mit neuen Befehlen neu gestartet werden, sondern könnte auf Basis neuer Eingaben selbst neue Unterroutinen schreiben und ausführen
    Das heißt, ein Programm könnte lernen und sich anpassen, indem es neue Abstraktionen schafft und sich an neue APIs anschließt
    Für mich ist das spannender als größere neuronale Netze oder neue Lernverfahren
  • Die Prämisse stimmt nicht
    Common Lisp hat Reader-Makros, mit denen man die Syntax beliebig ändern kann, und es gibt sogar einen Fortran-Compiler, der mit Reader-Makros Fortran-Syntax einliest
    Common Lisp hat Reader-Makros zur Lesezeit, Makros und Compiler-Makros zur Compile-Zeit, und alle diese Makrosprachen sind Common Lisp
    Metaprogrammierung hat nicht besonders viel mit Makros oder Syntax zu tun, sondern bezeichnet die Fähigkeit, Semantik und Bedeutung von Typen, Interfaces, Klassen, Methoden usw. zu manipulieren
    Wenn CL selbst dafür nicht stark genug ist, gibt es dafür CLOS, also das Common Lisp Metaobject Protocol
    • Gemeint ist hier das Reader-Makro-System von CL
      Mit CL-Reader-Makros kann man zwar einen anderen Tokenizer verwenden, aber man muss den Wechsel des Tokenizers durch einen Ausdruck in der Readtable signalisieren
      In Cognition scheint es so zu sein, dass beim Aufruf einer Funktion der Tokenizer des Aufruferkontexts mitgeändert wird
  • Das wirkt wie ein praktisches Beispiel dafür, eine Minimalmaschine zu einem Interpreter einer Hochsprache zu bootstrappen
    Warum uns beigebracht wurde, dass so etwas mit Turing-Maschinen oder Lambda-Kalkül wichtig ist, war zu zeigen, dass Hochsprachen den Basissprachen äquivalent sind und sich deshalb Schlussfolgerungen über Erstere auch auf Letztere übertragen lassen
    Das erste und einzige Beispiel, das mir dazu einfällt, ist das Halteproblem
    Kann man auf praktischer Größenordnung sagen, dass wenn sich beweisen lässt, dass die Basissprache keine Memory Leaks hat, dies dann auch für die abgeleitete Sprache gilt?
    Ich frage mich, welche Vorteile diese Art von Bootstrapping hat
    Und wenn die Antwort einfach wie beim Besteigen des Everest lautet: „weil er da ist“, dann respektiere ich auch das
  • Bei der Stelle, wo das Leerzeichen nach df, das Leerzeichen in Zeile 3 und der Zeilenumbruch wichtig sein sollen, war ich sofort bei „danke, aber nein danke“
    Die drei Leerzeichen am Ende der vorherigen Zeile markieren Sarkasmus und sollten dort, wo sich nachgestellte Leerzeichen nicht leicht erkennen lassen, wörtlich gelesen werden
    • Der Punkt dieses Experiments scheint zu sein, dass Forth ein nicht neu definierbares Zeichen hat, nämlich das Leerzeichen, und dass man schaut, was passiert, wenn man diese Einschränkung aufhebt
      Der erwähnte Bootstrapping-Teil ist tatsächlich die Stelle, an der dem Leser gesagt wird, er solle Leerzeichen und Zeilenumbrüche als Trennzeichen behandeln
      Man beschwert sich also darüber, dass Leerzeichen in einem Abschnitt Bedeutung haben, in dem sie ausdrücklich als Trennzeichen deklariert werden
      Natürlich darf man das so sehen, aber es lässt mich fragen, ob es dafür einen besseren Weg gegeben hätte
    • Diese Leerzeichen sind genau die Art und Weise, wie Leerzeichen, die zuvor nicht anders als andere Zeichen waren, tatsächlich zu Leerzeichen als solchen werden
      Zumindest einmal fällt mir kein Weg ein, das zu erreichen, ohne dass ein wörtliches Leerzeichen auf diese Weise Bedeutung bekommt
  • Es soll angeblich „eine Falle sein, irgendeine Form von Syntax zu haben“, aber Syntax gibt Struktur
    Glaubst du, man könnte einen Satz wie „diesen Satz ohne du Syntax lesen kannst“ lesen?
    Auch wenn Cognition vollständig postfixe Antisyntax verwendet, ist Postfix ebenfalls Syntax
    Frag einfach einen Deutschsprachigen nach Verben am Satzende
    Schon im ersten Beispiel ist die Reihenfolge von Operanden und Operatoren wichtig, und genau das ist Syntax
    Das wirkt wie der Versuch, eine absurd komprimierte Sprache zu bauen, und erinnert mich stark an APL
    Als Hinweis an die Autoren: Ihr habt die Syntax nicht abgeschafft, sondern sie nur für Menschen schwer lesbar und schwer verständlich gemacht, und Lesbarkeit und Verständlichkeit sind wichtige Faktoren beim Programmieren
  • Das war etwas schwer zu lesen
    Es fühlte sich an, als würden sich die Regeln unter den Füßen ständig ändern, als würden Regeln und Wörter eingeführt und dann willkürlich neu definiert
    Insgesamt hatte es etwas von Numberwang, was wohl einer der Gründe ist, warum es wie Satire wirkt
    Ein weiterer großer Grund ist, dass die Bootstrapping-Phase auf fast lächerliche Weise ausgeschrieben wurde, was offenbar beabsichtigt war
    Da steckt sicher etwas Tiefes drin, aber ich muss es nach stärkerem Kaffee noch einmal lesen
    • Es gibt viel zu erklären, und ich glaube auch, dass die jetzige Art der Erklärung nicht optimal war
      Ich bin der Autor dieses Textes, und das Problem ist, dass es wirklich sehr viel zu vermitteln gibt
      Matthew und ich haben drei Wochen lang jeden Tag mehrere Stunden über das Design dieser Sprache hin und her geschrieben, und es gibt tatsächlich viel Kontext, den ich für Leute nachliefern muss, die mich nicht kennen