| Paradigms | Multi-Paradigma: funktional, imperativ, meta |
|---|---|
| Entworfen von | Guy L. Steele und Gerald Jay Sussman |
| ] 1975 | |
| Stabile Veröffentlichung | R7RS / 2013 |
| Schreibweise | Dynamisch, latent, stark |
| Geltungsbereich | Lexical |
| Dateinamenserweiterungen | .scm, .ss |
| Website | www -reports |
| Wichtige Implementierungen | |
| Viele (siehe Schema-Implementierungen) | |
| Dialekte | |
| Schläger, T | |
| Beeinflusst durch | |
| ALGOL, Lisp, MDL | |
| Beeinflusst | |
| Clojure, Common Lisp, Dylan, EuLisp, Haskell, Hop, JavaScript, Julia, Lua, R., Ruby, Rust, S., Scala | |
Schema [19456531] ist eine Programmiersprache, die mehrere Paradigmen, einschließlich funktionaler, unterstützt und imperative Programmierung. [1] Es ist neben Common Lisp einer der beiden wichtigsten Dialekte von Lisp. Im Gegensatz zu Common Lisp folgt Scheme einer minimalistischen Designphilosophie und legt einen kleinen Standardkern mit leistungsstarken Werkzeugen für die Spracherweiterung fest.
Scheme wurde in den 1970er Jahren im MIT AI Lab erstellt und von seinen Entwicklern Guy L. Steele und Gerald Jay Sussman über eine Reihe von Memos veröffentlicht, die jetzt als Lambda Papers bekannt sind. Es war der erste Dialekt von Lisp, der den lexikalischen Geltungsbereich auswählte und der erste, der Implementierungen zur Durchführung der Rückrufoptimierung erforderte, wodurch die funktionale Programmierung und damit verbundene Techniken wie rekursive Algorithmen stärker unterstützt werden. Es war auch eine der ersten Programmiersprachen, die erstklassige Fortsetzungen unterstützte. Es hatte einen wesentlichen Einfluss auf die Bemühungen, die zur Entwicklung von Common Lisp führten. [2]
Die Schemasprache ist im offiziellen IEEE-Standard [3] und einem De-facto-Verfahren standardisiert. Standard als der überarbeitete n Bericht über das algorithmische Sprachschema (R n RS) bezeichnet. Der am weitesten verbreitete Standard ist R5RS (1998), [4] ein neuer Standard, R6RS [5] der 2007 ratifiziert wurde. [6] Scheme hat aufgrund seiner Kompaktheit und Eleganz eine vielfältige Anwenderbasis, aber auch seine minimalistische Philosophie verursachte große Unterschiede zwischen den praktischen Implementierungen, so sehr, dass der Lenkungsausschuss des Programms dies als "die nicht portierbare Programmiersprache der Welt" und "eine Familie von Dialekten" bezeichnet, und nicht eine einzige Sprache. [7]
History edit ]
Origins [ edit ]
Das Programm begann in den 70er Jahren als ein Versuch, das Modell von Carl Hewitt Actor zu verstehen, zu welchem Zweck Steele und Sussman schrieben ein "winziger Lisp-Interpreter" mit Maclisp und "fügte Mechanismen hinzu, um Akteure zu erstellen und Nachrichten zu senden". [8] Das Schema hieß ursprünglich "Schemer", in der Tradition anderer von Lisp abgeleiteter Sprachen wie Planner oder Conniver . Der aktuelle Name resultierte aus der Verwendung des ITS-Betriebssystems durch die Autoren, das Dateinamen auf zwei Komponenten mit jeweils höchstens sechs Zeichen beschränkte. Derzeit wird "Schemer" üblicherweise für einen Scheme-Programmierer verwendet.
R6RS [ edit ]
Beim Scheme-Workshop 2003 begann ein neuer Standardisierungsprozess für Sprachen, mit dem Ziel, 2006 einen R6RS-Standard zu erstellen. Dieser Prozess brach mit dem früheren n Einstimmigkeit der RS.
R6RS verfügt über ein Standardmodulsystem, das eine Trennung zwischen Kernsprache und Bibliotheken ermöglicht. Eine Reihe von Entwürfen der R6RS-Spezifikation wurde veröffentlicht, die endgültige Version war R5.97RS. Eine erfolgreiche Abstimmung führte zur Ratifizierung des neuen Standards, der am 28. August 2007 bekanntgegeben wurde. [5]
Derzeit unterstützen die neuesten Versionen verschiedener Scheme-Implementierungen [9] den R6RS-Standard. Es gibt eine portierbare Referenzimplementierung der vorgeschlagenen implizit gestaffelten Bibliotheken für R6RS mit dem Namen psyntax, die sich bei verschiedenen älteren Scheme-Implementierungen ordnungsgemäß lädt und bootstraps. [10]
Ein Merkmal von R6RS ist die Aufzeichnung. Typdeskriptor (RTD). Wenn ein RTD erstellt und verwendet wird, kann die Darstellung des Datensatztyps das Speicherlayout anzeigen. Es berechnete auch Objektfeld-Bitmaske und veränderliche Scheme-Objektfeld-Bitmasken und half dem Speicherbereiniger, zu wissen, was mit den Feldern zu tun ist, ohne die gesamte Feldliste zu durchlaufen, die im RTD gespeichert ist. Mithilfe von RTD können Benutzer die grundlegende RTD erweitern, um ein neues Rekordsystem zu erstellen. [11]
R6RS führt zahlreiche bedeutende Änderungen an der Sprache ein. [12] Der Quellcode ist jetzt in Unicode angegeben, und a Eine große Teilmenge von Unicode-Zeichen kann jetzt in Schemasymbolen und -bezeichnern erscheinen, und es gibt weitere geringfügige Änderungen an den lexikalischen Regeln. Zeichendaten werden jetzt auch in Unicode angegeben. Viele Standardverfahren wurden in die neuen Standardbibliotheken verlagert, die selbst eine große Erweiterung des Standards darstellen und Prozeduren und syntaktische Formen enthalten, die zuvor nicht zum Standard gehörten. Ein neues Modulsystem wurde eingeführt und Systeme für die Ausnahmebehandlung sind jetzt standardisiert. Die Syntaxregeln wurden durch eine ausdrucksstärkere syntaktische Abstraktionsfunktion (Syntaxfall) ersetzt, die die Verwendung des gesamten Schemas bei der Makroerweiterung ermöglicht. Konforme Implementierungen sind jetzt erforderlich um den gesamten numerischen Turm von Scheme zu unterstützen, und die Semantik der Zahlen wurde erweitert, hauptsächlich in Richtung der Unterstützung des IEEE 754-Standards für die numerische Darstellung von Fließkommazahlen.
R7RS [ edit ]
Der R6RS-Standard hat zu Kontroversen geführt, da er sich von der minimalistischen Philosophie entfernt hat. [13][14] Im August 2009 befand sich der Lenkungsausschuss des Scheme, dem beaufsichtigt den Standardisierungsprozess und kündigte seine Absicht an, die Aufteilung in zwei Sprachen zu empfehlen: eine große moderne Programmiersprache für Programmierer; und eine kleine Version, eine Untermenge der großen Version, die den von Pädagogen und Gelegenheitsimplikatoren gepriesenen Minimalismus beibehält. [7] Zwei Arbeitsgruppen wurden geschaffen, um an diesen beiden neuen Versionen von Scheme zu arbeiten. Die Website für den Prozess Scheme Reports enthält Links zu den Chartas der Arbeitsgruppen, zu öffentlichen Diskussionen und zum Problemverfolgungssystem.
Der neunte Entwurf von R7RS (kleine Sprache) wurde am 15. April 2013 zur Verfügung gestellt. [15] Eine Abstimmung über diesen Entwurf wurde am 20. Mai 2013 geschlossen, [16] und der Abschlussbericht liegt seit dem 6. August vor. 2013, in dem er "die" kleine "Sprache dieser Bemühungen beschreibt: Daher kann sie nicht isoliert als Nachfolger von R6RS betrachtet werden." [17]
Unterscheidungsmerkmale [ edit
Das Schema ist in erster Linie eine funktionale Programmiersprache. Es teilt viele Eigenschaften mit anderen Mitgliedern der Lisp-Programmiersprachenfamilie. Die sehr einfache Schemasyntax basiert auf s-Ausdrücken, Listen in Klammern, in denen ein Präfixoperator seinen Argumenten folgt. Schemaprogramme bestehen somit aus Sequenzen verschachtelter Listen. Listen sind auch die Hauptdatenstruktur in Scheme, was zu einer engen Entsprechung zwischen Quellcode und Datenformaten (Homoikonizität) führt. Scheme-Programme können auf einfache Weise Teile des Schemacodes dynamisch erstellen und auswerten.
Das Vertrauen auf Listen als Datenstrukturen wird von allen Lisp-Dialekten gemeinsam genutzt. Das Schema erbt eine reiche Menge von Listen verarbeitenden Grundelementen wie cons car und cdr von seinen Lisp-Vorläufern. Das Schema verwendet streng aber dynamisch typisierte Variablen und unterstützt erstklassige Prozeduren. Prozeduren können daher Variablen als Werte zugewiesen oder als Argumente an Prozeduren übergeben werden.
Dieser Abschnitt konzentriert sich hauptsächlich auf innovative Merkmale der Sprache, einschließlich der Merkmale, die Scheme von anderen Lisps unterscheiden. Sofern nicht anders angegeben, beziehen sich die Beschreibungen der Funktionen auf den R5RS-Standard.
In den Beispielen in diesem Abschnitt wird die Notation "===> result" verwendet, um das Ergebnis der Auswertung des Ausdrucks in der unmittelbar vorhergehenden Zeile anzugeben. Dies ist die gleiche Konvention, die in R5RS verwendet wird.
Grundlegende Konstruktionsmerkmale [ edit ]
In diesem Unterabschnitt werden die Merkmale des Scheme beschrieben, die es von seinen frühesten Tagen an von anderen Programmiersprachen unterschieden haben. Dies sind die Aspekte des Schemas, die am stärksten Einfluss auf jedes Produkt der Schemasprache haben, und dies sind die Aspekte, die alle Versionen der Programmiersprache Scheme ab 1973 gemeinsam haben.
Minimalism [ edit ]
Schema ist eine sehr einfache Sprache, die viel einfacher zu implementieren ist als viele andere Sprachen mit vergleichbarer Ausdruckskraft. [18] Diese Leichtigkeit ist auf die Verwendung von zurückzuführen Lambda-Kalkül, um einen Großteil der Syntax der Sprache aus primitiveren Formen abzuleiten. Zum Beispiel der 23 s-expression-basierten syntaktischen Konstrukte, die im R5RS-Scheme-Standard definiert sind, 14 werden als abgeleitete oder Bibliotheksformen klassifiziert, die als Makros geschrieben werden können, die weitere Grundformen, hauptsächlich Lambda, verwenden. Wie R5RS sagt (R5RS, Abschnitt 3.1): "Das grundlegendste der variablen Bindungskonstrukte ist die Lambda-Expression, da alle anderen variablen Bindungskonstrukte in Form von Lambda-Ausdrücken erklärt werden können." [4]
- Fundamental forms : define , lambda, quot, if, define-Syntax, Let-Syntax, Letrec-Syntax, Syntax-Regeln, Set!
- Abgeleitete Formulare : do, let, let *, letrec, cond, case und und , begin, named let, delay, unquote, unquote-splicing, quasiquote
Beispiel: Ein Makro zum Implementieren let als Ausdruck, wobei Lambda verwendet wird, um die variablen Bindungen auszuführen.
( define-syntax let ( syntax-rules () (19659079] let var var expr ) ... ) body ... ) (( lambda var var var . .. ) body ... ) expr ... )))) So sei Wie oben definiert, würde eine Scheme-Implementierung " (let ((a 1) (b 2)) (+ ba)) " als " ((lambda (ab) (+ ba)) 1 2 umschreiben ) ", wodurch die Aufgabe der Implementierung auf die Codierung von Instanziierungen reduziert wird.
Sussman und Steele bemerkten 1998, dass der Minimalismus von Scheme kein bewusstes Designziel sei, sondern eher das unbeabsichtigte Ergebnis des Designprozesses. "Wir haben tatsächlich versucht, etwas Kompliziertes zu bauen und haben dabei zufällig entdeckt, dass wir aus Versehen etwas entworfen hatten, das alle unsere Ziele erfüllte, aber viel einfacher war, als wir beabsichtigt hatten. Wir erkannten, dass der Lambda-Kalkül - ein kleiner, einfacher Formalismus - war. könnte als Kern einer mächtigen und ausdrucksstarken Programmiersprache dienen. "[8]
Lexikalischer Bereich [ edit ]
Wie die meisten modernen Programmiersprachen und im Gegensatz zu früheren Lisps wie Maclisp ist das Schema lexikalisch Geltungsbereich: Alle möglichen Variablenbindungen in einer Programmeinheit können analysiert werden, indem der Text der Programmeinheit gelesen wird, ohne die Kontexte zu berücksichtigen, in denen sie aufgerufen werden kann. Dies steht im Gegensatz zum dynamischen Scoping, das für frühe Lisp-Dialekte charakteristisch war, aufgrund der Verarbeitungskosten, die mit primitiven Textsubstitutionsmethoden verbunden sind, die zur Implementierung lexikalischer Scoping-Algorithmen in Compilern und Interpreten des Tages verwendet werden. In diesen Lisps war es durchaus möglich, dass ein Verweis auf eine freie Variable innerhalb einer Prozedur auf recht unterschiedliche Bindungen außerhalb der Prozedur verweist, abhängig vom Kontext der Aufforderung.
Der Anstoß, das lexikalische Scoping, das in den frühen 1970er Jahren ein ungewöhnliches Scoping-Modell war, in ihre neue Version von Lisp zu integrieren, stammt von Sussmans Studien über ALGOL. Er schlug vor, dass ALGOL-artige lexikalische Scoping-Mechanismen dazu beitragen würden, ihr ursprüngliches Ziel der Umsetzung des Actor-Modells von Hewitt in Lisp zu erreichen. [8]
Die wichtigsten Erkenntnisse darüber, wie lexikalisches Scoping in einen Lisp-Dialekt eingeführt werden sollte, waren in Sussman und Steeles Lambda-Papier von 1975, "Schema: Ein Interpreter für erweiterten Lambda-Kalkül", [19] in dem sie das Konzept des lexikalischen Schließens (auf Seite 21) übernahmen, das 1970 von Joel in einem AI Memo beschrieben worden war Moses, der die Idee auf Peter J. Landin zurückführte [20]
Lambda-Kalkül [ edit ]
Die mathematische Notation der Alonzo-Kirche, der Lambda-Kalkül, hat Lisp als "Lambda" bezeichnet ein Schlüsselwort zur Einführung eines Verfahrens sowie zur Beeinflussung der Entwicklung funktionaler Programmiertechniken unter Verwendung von Funktionen höherer Ordnung in Lisp. Frühe Lisps waren jedoch aufgrund ihrer Behandlung von freien Variablen keine geeigneten Ausdrücke des Lambda-Kalküls. [8]
Ein formelles Lambda-System hat Axiome und eine vollständige Berechnungsregel. Es ist hilfreich für die Analyse mit mathematischer Logik und Werkzeugen. In diesem System kann die Berechnung als Richtungsabzug betrachtet werden. Die Syntax des Lambda-Kalküls folgt den rekursiven Ausdrücken aus x, y, z, ..., Klammern, Leerzeichen, der Periode und dem Symbol λ. [21] Die Funktion der Lambda-Berechnung umfasst: Erstens: Als Ausgangspunkt für mächtig mathematische Logik. Zweitens kann die Anforderung von Programmierern, die Implementierungsdetails zu berücksichtigen, reduziert werden, da sie die Maschinenbewertung imitieren kann. Die Lambda-Berechnung führte schließlich zu einer umfassenden Metatheorie. [22]
Die Einführung des lexikalischen Anwendungsbereichs löste das Problem, indem eine Äquivalenz zwischen einigen Formen der Lambda-Notation und ihrem praktischen Ausdruck in einem Arbeitsprogramm hergestellt wurde Sprache. Sussman und Steele zeigten, dass die neue Sprache verwendet werden kann, um alle imperativen und deklarativen Semantiken anderer Programmiersprachen einschließlich ALGOL und Fortran sowie den dynamischen Geltungsbereich anderer Lisps auf elegante Weise abzuleiten, indem Lambda-Ausdrücke nicht als einfache Prozedurinstanziierungen, sondern als "Kontrolle" verwendet werden Strukturen und Modifikatoren für die Umgebung ". [23] Sie führten den Stil der Fortführung durch, zusammen mit ihrer ersten Beschreibung des Schemas in der ersten der Lambda-Papiere, und in nachfolgenden Papieren demonstrierten sie die rohe Kraft dieser praktischen Verwendung des Lambda-Kalküls.
Blockstruktur [ edit ]
Das Schema erbt seine Blockstruktur von früheren blockstrukturierten Sprachen, insbesondere von ALGOL. In Schema werden Blöcke durch drei bindende Konstrukte implementiert: let let * und letrec . Das folgende Konstrukt erstellt beispielsweise einen Block, in dem ein Symbol mit dem Namen var an die Zahl 10 gebunden ist:
( definieren var "Gans" ) ; Jede Bezugnahme auf var wird hier an "Gans" gebunden sein ( let (([ var 10 )) ; Erklärungen hier var wird hier an 10 gebunden. ) ;; Jeder Verweis auf var wird an "goose" gebunden sein. Blöcke können verschachtelt werden, um beliebig komplexe Blockstrukturen entsprechend den Anforderungen des Programmierers zu erstellen. Die Verwendung der Blockstrukturierung zum Erstellen lokaler Bindungen verringert das Risiko einer Namensraumkollision, die andernfalls auftreten kann.
Eine Variante von let let * erlaubt Bindungen, sich auf Variablen zu beziehen, die zuvor im selben Konstrukt definiert wurden, also:
( sei * (( var1 10 ) ( var2 ( + var1 12 ))) ;; Aber die Definition von var1 konnte sich nicht auf var2 ) beziehen. Die andere Variante, letrec soll das Binden wechselseitig rekursiver Verfahren ermöglichen zueinander.
;; Berechnung der männlichen und weiblichen Sequenzen von Hofstadter als Liste von Paaren ( definieren ( hofstadter-männlich-weiblich n ) (19659079] letrec ] (( weiblich ( lambda ( n ) ( wenn ( = n [28] 0 ) 1 ( - n ( männlich) ( weiblich 19659135] 1 )))))))) ( männlich ( lambda ( n )
No comments:
Post a Comment