Racket (Programmiersprache)
Racket ist eine multi-paradigmatische Programmiersprache aus der Lisp-Scheme-Familie. Sie ist Nachfolger des Scheme-Dialekts PLT Scheme. Racket besitzt eine integrierte Entwicklungsumgebung (IDE), DrRacket, und eine umfangreiche Bibliothek. 2018 erhielt Racket den Programming Languages Software Award von ACM SIGPLAN. In der Laudatio wurde Rackets singuläre Bedeutung sowohl für Forschung als auch Lehre von Programmiersprachen über rund zwanzig Jahre hervorgehoben.[2] Racket ist eine Programmiersprache zur Erzeugung und Erweiterung (Language Extensibility) von Programmiersprachen. Es spielt eine wichtige Rolle in der Forschung zu rekursiven Modulen 1. Klasse, Gradual Typing, Functional Reactive Programming und Kontrakten höherer Ordnung. DrRacket fand Verbreitung in Einführungskursen zu Programmiersprachen und bei neueren Lehrbüchern.[3][4] Racket ist Open-Source-Software unter GNU Lesser General Public License bzw. MIT-Lizenz und Apache-Lizenz.[5] Code-BeispieleDas klassische Hallo-Welt-Programm: #lang racket/base
"Hello, World!"
Quadrieren einer Liste in der Basissprache #lang racket/base
(define liste '(1 2 3 4 5)) ; Typ der Liste wird zur Laufzeit ermittelt
(define (quadrieren x) ; Keine Typfestlegung der Funktion "quadrieren"
(* x x)) ; Fehler werden erst zur Laufzeit festgestellt
(displayln (map quadrieren liste)) ; (1 4 9 16 25)
Quadrieren einer Liste im Dialekt #lang typed/racket
(define liste : (Listof Integer) '(1 2 3 4 5)) ; Typfestlegung der Liste
(: quadrieren (-> Integer Integer)) ; Typfestlegung der Funktion "quadrieren"
(define (quadrieren x)
(* x x))
(displayln (map quadrieren liste)) ; (1 4 9 16 25)
Durch Nutzung von > liste
- : (Listof Integer)
'(1 2 3 4 5)
> quadrieren
- : (-> Integer Integer)
#<procedure:quadrieren>
Ausschnitt einer Markdown-Vorlagen-Datei #lang pollen
◊(define beruf "Arzt")
◊(define wohnort "Berlin")
◊(define kinder (* 2 2))
Mein Name ist _Max_ _Mustermann_,
* ich bin von Beruf ◊beruf
* wohne in ◊wohnort
* habe ◊kinder Kinder
In der entsprechenden Markdown-Datei Mein Name ist _Max_ _Mustermann_,
* ich bin von Beruf Arzt
* wohne in Berlin
* habe 4 Kinder
![]() Generierung eines Sierpinski-Dreiecks: #lang racket
(require 2htdp/image)
(let sierpinski ([n 8])
(if (zero? n)
(triangle 2 'solid 'red)
(let ([t (sierpinski (- n 1))])
(freeze (above t (beside t t))))))
Die grafische Ausgabe des Sierpinski-Dreiecks ist in der Abbildung rechts dargestellt. Sprachorientierte ProgrammierungIn Racket steht die Erzeugung von domänenspezifischen Sprachen oder Allzwecksprachen im Mittelpunkt. Jede Sprache, die in Racket implementiert wird, muss zwei Bestandteile aufweisen: einen sog. Reader, der vereinfacht ausgedrückt den Quellcode einliest, und einen sog. Expander, der den Quellcode interpretiert.[8] Für eine Sprache #lang racket
(define (read-syntax path port)
(define code-zeilen (port->lines port)) ; Einlesen des Codes
#`(module module-name racket/base ; Modul als Syntax-Objekt anlegen (Expander racket/base)
(for ([code-zeile (list #,@code-zeilen)]) ; Code-Zeilen einspleißen und for-Schleife anlegen
(writeln code-zeile)))) ; Code-Zeilen auf Terminal ausgeben
(provide read-syntax) ; read-syntax zur Verfügung stellen
Dieser liest den Code zeilenweise ein und erzeugt ein Syntax-Objekt (mit Nun speichert man den Code in einer Datei #lang reader "minilang.rkt" ab cd ef an. Diese kann man nun in DrRacket (oder mit "" "" "ab" "cd" "ef" Hier ist zu beachten, dass der Reader nur das Syntax-Objekt zurückgibt, der Code selbst aber erst später ausgeführt wird. Wenn die Strings der Code-Zeilen modifiziert werden sollen (beispielsweise um Vorformatierungen vorzunehmen), dann kann man das Einspleißen im Syntax-Objekt verändern. Dies könnte zum Beispiel so aussehen: #lang racket
(define (read-syntax path port)
(define code-zeilen (port->lines port))
(define veraenderte-code-zeilen
(map (lambda (s) `(veraendere ,s)) ; Strings mit Präfix "veraendere" versehen
code-zeilen))
#`(module module-name "minilang2-expander.rkt" ; Eigenen Expander verwenden
(for ([code-zeile (list #,@veraenderte-code-zeilen)])
(writeln code-zeile))))
(provide read-syntax)
Hier werden die Strings aus den Code-Zeilen mit einem Präfix „veraendere“ versehen und als Liste von Datums-Objekten gespeichert. Diese Liste wird in die Schleife innerhalb des Syntax-Objekts eingespleißt. Das bedeutet, dass jeder String mit einer Funktion #lang racket
(define (veraendere s) ; Funktion String -> String
(string-append "veraendert " s)) ; "string" -> "veraendert string"
(provide veraendere) ; Stelle Funktion "veraendere" zur Verfügung
Führt man das "veraendert " "veraendert " "veraendert ab" "veraendert cd" "veraendert ef" Der gezeigte Reader erzeugt eine Terminalausgabe, wenn man die Quelldatei #`(module module-name "minilang2-expander.rkt"
(define export-daten (list #,@veraenderte-code-zeilen))
(provide export-daten))
Hier werden die erzeugten Strings in einer Liste #lang racket
(require "testminilang.rkt")
(writeln export-daten) ; ("veraendert " "veraendert " "veraendert ab" "veraendert cd" "veraendert ef")
kann man auf In den vorangegangenen Beispielen ist eine Art Syntax und Semantik implementiert worden. Oft wird in Racket die Syntax nur leicht modifiziert (weiterhin sog. S-Expressions), aber neue Funktionalität mit Hilfe von Makros hinzugefügt. Diese dienen dazu, Syntax-Objekte ineinander zu transformieren. Hier spielen auch die verschiedenen Phasen (Phase 0 – Laufzeitphase, Phasen – Übersetzungsphasen) in Racket eine Rolle, in die man ebenfalls eingreifen kann. Wenn man neue Syntax (abseits von S-Expressions) einführt, ist es oft einfacher, das Einlesen im Reader in mehrere Schritte zu unterteilen. Dies sind im Einzelnen das Zerlegen des Eingabestrings in irreduzible Elemente der Sprache (Tokenizer, Lexer) und das Prüfen und Umwandeln dieser Elemente in das Syntax-Objekt entsprechend einer Grammatik (Parser). Dies wird in der zitierten Literatur ausführlich dargestellt. Weblinks
Einzelnachweise |
Portal di Ensiklopedia Dunia