Programmieren lernen mit A++ - Georg P. Loczewski - E-Book

Programmieren lernen mit A++ E-Book

Georg P. Loczewski

0,0

Beschreibung

A++ ist eine Programmiersprache, die an Minimalismus nicht zu übertreffen ist. Ihr einziger Zweck ist es, an der Programmierung Interessierten zu helfen, so schnell und effizient wie nur möglich das Wesentliche der Programmierung zu erfassen. In verhältnismäßig kurzer Zeit werden Denkmuster eingeübt, die einen befähigen, sich müheloser in die großen populären Programmiersprachen einzuarbeiten, um in ihnen produktiv werden zu können. In diesem Buch werden die Programmiersprachen Python und Java vorgestellt und es wird gezeigt, wie A++-orientierte Programmierung in diesen Sprachen angewandt werden kann. Umfangreiche Fallstudien werden als Hilfe zum Erlernen der Programmierung angeboten. Ein zur Verfügung gestellter Interpreter soll dabei behilflich sein, das Gelernte anzuwenden und zu testen. Eine Einführung in das Lambda-Kalkül von Alonzo Church, das die theoretische Grundlage von A++ darstellt, ist im Anhang enthalten. Das Buch wendet sich an alle Personen, die sich mit dem Erlernen der Kunst der Programmierung befassen. Dies sind vor allem Lehrende und Lernende an Hochschulen und den Oberstufen von Gymnasien in den Fachbereichen der Informatik, der Mathematik und der Physik.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern
Kindle™-E-Readern
(für ausgewählte Pakete)

Seitenzahl: 231

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Programmieren lernen mit

A++

Georg P. Loczewski

Programmieren lernen mit A++

Funktional programmieren in Python und Java

Mit einer Einführung in das Lambda-Kalkül

IMPRESSUM

Copyright © 2018 Georg P. Loczewski

Programmieren lernen mit A++

1. Auflage 2018 –Hamburg

Verlag: tredition GmbH

2. Auflage 2018 –Hamburg

Verlag: tredition GmbH

ISBN

978-3-7469-3199-9 (Paperback)

978-3-7469-3200-2 (Hardcover)

978-3-7469-3201-9 (e-Book)

Verlag & Druck: tredition GmbH

Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung, noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und etwaige Hinweise auf Fehler sind Verlag und Autor dankbar. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig.

Das Werk einschließlich all seiner Teile ist urheberrechtlich geschützt. Jede Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Das gilt insbesondere für Verfielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeisung, Verarbeitung und Verbreitung in elektronischen Systemen.

Meiner Frau Ursulaund meinen Söhnen Thomas und Johannesin Liebe gewidmet

Inhaltsverzeichnis

Vorwort

I Grundlagen

1 Einführung

1.1 Konstitutive Prinzipien in A++

Abstraktion
Referenz
Synthese
Closure
Lexical Scope

2 Sprachdefinition

2.1 Syntax und Semantik von A++

Anmerkungen zur Syntax:

2.2 Beispiele zur Syntax von A++

Beispiele zur Abstraktion 1. Alternative in 2.2
Beispiele zur Abstraktion 2. Alternative in 2.2
Beispiele zur Referenz 2.3
Beispiele zur Synthese 2.4

2.3 A++ Erweiterung

Syntax von A++ mit vorgegebenen Primitiv-Abstraktionen
Beispiele zu den Erweiterungen in A++

3 Erste Entfaltung von A++

3.1 Programmierstil in A++

3.2 Grundlegende Logische Abstraktionen

Abstraktionen ‘true’ und ‘false’
Abstraktionen ‘lif’

3.3 Erweiterte Logische Abstraktionen

3.4 Numerische Abstraktionen

Abstraktion für die Zahl ‘0’
Abstraktion für die Zahl ‘1’
Abstraktion für die Zahl ‘2’
Abstraktion für das Prädikat ‘zerop’
Abstraktion für die Zahl ‘3’
Utility-Abstraktion ‘compose’
Abstraktion für die Addition
Abstraktion für die Inkrementierung
Abstraktion für die Multiplikation

3.5 Abstraktionen für Listen

Abstraktion für den Konstruktor
Abstraktion für den Selektor ‘lcar’
Abstraktion für den Selektor ‘lcdr’
Anwendung der grundlegenden Operationen für Listen
Abstraktion für das Ende einer Liste
Abstraktion für das Prädikat ‘nullp’
Abstraktion für die Längenabfrage
Abstraktion zum Entfernen eines Objektes aus einer Liste

3.6 Erweiterte Arithmetische Abstraktionen

Abstraktion für ‘zeropair’
Abstraktion für die Dekrementierung
Abstraktion für die Subtraktion

3.7 Relationale Abstraktionen

Abstraktion für das Prädikat ‘gleich’
Abstraktion für das Prädikat ‘größer als’
Abstraktion für das Prädikat ‘kleiner als’
Abstraktion für das Prädikat ‘größer gleich’

3.8 Funktionen Höherer Ordnung

Abstraktion ‘compose’
Abstraktion für die ‘curry’-Funktion
Abstraktion für die Abbildung einer Liste
Abstraktion für die ‘curry map’-Funktion
Abstraktion für die Auswahl aus einer Liste
Abstraktion für die Suche nach einem Objekt in einer Liste

3.9 Mengen-Operationen

Abstraktion für das Prädikat ‘memberp’
Abstraktion für das Hinzufügen eines Elementes
Abstraktion für die Vereinigung von Mengen

4 Erste Anwendung von A++

4.1 Utility-Abstraktionen

Abstraktion für das sortierte Einfügen in eine Liste
Abstraktion für die Sortierung

4.2 Rekursion

Abstraktion für die Berechnung der Fakultät
Abstraktion für die Summation
Abstraktion für den Zugriff auf ein Element einer Liste
Abstraktion für die Iteration über die Elemente einer Liste

4.3 Imperative Programmierung in A++

Die Abstraktion ’while’ in A++

5 Objekt-Orientierte Anwendung von A++

5.1 Einleitung

Bildung von Klassen
Instanzen von Klassen
Beispiele für Objekt-orientierung in A++

5.2 Erstes Beispiel zur Objektorientierung in A++

Konstruktor für Objekte der Klasse “account”
Erzeugung des Objektes “acc1” durch Aufruf von “make-account”
Senden der Botschaft “deposit” an das Objekt “acc1”
Ausführen der Funktion “deposit”
Detaillierter Code in A++
Anmerkungen zu dem ersten Beispiel zur Objektorientierung
Anmerkungen zum Aufruf der Funktion ‘konto’

5.3 Zweites Beispiel zur Objektorientierung in A++

Anmerkung zu den einzelnen Klassen
Beziehungen zwischen den Klassen
Zusammenfassung

5.4 Drittes Beispiel zur Objektorientierung in A++

Anmerkung zu den einzelnen Klassen

6 Abstraktion, Referenz und Synthese im Detail

6.1 Addition der zwei Zahlen ‘two’ und ‘three’

Synthese von ‘add’ und ‘two three’ (1)
Abstraktion von ‘add’ (1)
Auflösung der Referenz von ‘add’ in [1]
Synthese von (lambda(m n) …) und ‘two three’ in [3]
Abstraktion von ‘compose’
Auflösung der Referenz von ‘compose’ in [4]
Synthese von (lambda(f g) …) und ‘(two f) (three f)’ in [6]
Abstraktion von three:
Auflösung der Referenz von ‘three’ in [7]
Synthese von (lambda(f) …) und ‘f’ in [9]
Synthese von (lambda(x) …) und ‘x’ in [10]
Abstraktion von two:
Auflösung der Referenz von ‘two’ in [11]
Synthese von (lambda(f) …) und ‘f’ in [13]
Synthese vom inneren (lambda(x) …) und ‘(f (f (f x)))’ in [14]

6.2 Multiplikation der zwei Zahlen ‘two’ und ‘three’

Synthese von mult und ‘two three’
Abstraktion von mult:
Auflösung der Referenz von ‘mult’ in [17]
Synthese von (lambda(m n) …) und ‘two three’ in [19]
Abstraktion von compose:
Auflösung der Referenz von ‘compose’ in [20]
Synthese von (lambda(f g) …) und ‘two three’ in [22]
Abstraktion von two:
Abstraktion von three:
Auflösung der Referenz von ‘two’ und ‘three’ in [23]
Synthese vom inneren (lambda(f) …) und ‘x’ in [26]
Synthese von (lambda(f) …) und ‘(lambda(x0) …)’ in [28]
Synthese vom inneren (lambda(x0) …) und ‘x1’
Synthese von (lambda(x0) …) und ‘(x(x(x x1)))’
Umbenennung der Variablen: x –> f und x1 –> x

7 Infrastruktur für A++

7.1 Support-Funktionen

Abstraktion für die Ausgabe einer Zahl
Abstraktion für die Ausgabe eines boole’schen Wertes
Abstraktion für die Ausgabe von Listen

7.2 A++ Interpreter

Linux
MS-Windows
Programmbeendigung

7.3 Initialisierungsdatei für den ARS-Interperter

7.4 WWW-Adressen

8 Erweiterung von A++

8.1 ARS++

8.2 ARSAPI

II ARS und Pyhon

9 Programmierung in Python

9.1 Allgemeine Syntax von Python

9.2 Wichtige Abstraktionsmechanismen

Bildung von Funktionen
Bildung von Klassen
Bildung von Modulen

9.3 Operationen in Funktionen

Definition von Variablen
Definition von Funktionen
Erzeugung von Objekten
Zuweisung von Werten
Testen von Werten
Wiederholung von Operationen
Rekursion
Ein-/Ausgabe-Operationen
Arithmetische Operationen
Relationale Operationen
Boolesche Operationen

9.4 Grundlegende Datentypen

Atome
Listen
Methoden für Listenobjekte
Hilfsfunktionen für Listen

9.5 Dictionaries

Methoden für Assoziative Listen
Hash-Tabellen

9.6 Besonderheiten in Python

10 ARS-Interpreter in Python

10.1 Einleitung

Syntax eines Lambda-Ausdrucks in EBNF-Notation:
Komponenten des Interpreters

10.2 Klasse X

10.3 Globale Variable

10.4 Klasse ARSSymbol

10.5 Klasse ARSToken

10.6 Klasse für den Parser: ARSParser

10.7 Klasse ARSClosure

10.8 Funktionen für die Auswertung von Ausdrücken

10.9 Klasse Interpreter

10.10 Austesten des Interpreters

10.11 Quellcode des Interpreters

10.12 Kompatibilitäts Modul für Listen

III ARS und Java

11 Programmierung in Java

11.1 Zweck und Umfang der Einführung in Java

11.2 Wichtige Abstraktionsmechanismen

Etwas einen Namen geben
Bildung von Klassen

11.3 Closures

11.4 Operationen in Funktionen

Allgemeine Grundfunktionen
Praktische Konkretisierung der allgemeinen Grundfunktionen
Bildung von Funktionen

11.5 Grundlegende Datentypen

Atom
Listen
Verarbeitung von Listen
Implementierung von Listen in Java
Dictionaries

11.6 Besonderheiten in Java

Fehler-Behandlung mit “try” und “catch”
“Threads”

11.7 Alternative Implementierung von Closures in Java

Datentypen-Überblick
Umgebung einer Lambda-Abstraktion
Klasse LClosure
Anwendungsbeispiele

12 ARS-Interpreter in Java

12.1 Einleitung

Syntax eines Lambda-Ausdrucks in EBNF-Notation:
Funktion und Struktur des Interpreters

12.2 Klasse für Symbole: Symbol

12.3 Klasse für Token: ARSToken

12.4 Klasse für den Parser: ARSParser

12.5 Klasse für Closures: ARSClosure

12.6 Klasse für den Evaluator: ARSEval

12.7 Klasse für die Fehlerbehandlung: ARSException

12.8 Klasse: ARSInterpreter

13 Komplette Anwendung in Java: OntoSimula

13.1 Einleitung

Simulation des Lebens von fünf Philosophen
Als ‘applet’ im Internet ausführbar
Detailliertes Szenario

13.2 Quellen für die Entwicklung der Fallstudie

13.3 Dynamisches Objektsystem für Java

Überblick
Klasse LJoops
Klasse LJoopsError
Klasse LJClasstable
Klasse LJclass
Klasse LJobject
Testprogramm für LJoops

13.4 Lambda-Klassen in Java

Überblick

13.5 Applet-Steuerklasse: PhilGraph

Darstellung auf dem Bildschirm
Ausführung in der Java-VM

13.6 Haupt-Anwendungsklasse OntoSimula

Dynamische Klassen

13.7 Haupt-Graphikklassen

Klasse für das Schloss: PhilCastle
Klasse für die Bedieneroberfläche

13.8 Statische Klassen für Sachen

Basis-Klasse ElementD
Klasse Chopstick
Klasse Room

13.9 Klassen für graphische Objekte

Basisklasse ImageObjectD
Klasse PersonImage
Klasse ChopstickImage
Hilfsklasse Semaphore

13.10 Methoden zur Auswahl des Verhaltensmusters

Methoden zur Auswahl des Verhaltensmusters für Aristoteles
Methoden zur Auswahl des Verhaltensmusters für Heraklit
Methoden zur Auswahl des Verhaltensmusters für Parmenides
Methoden zur Auswahl des Verhaltensmusters für Plato
Methoden zur Auswahl des Verhaltensmusters für Sokrates

13.11 Verhaltensmuster für alle Philosophen

Verhaltensmuster für heroische Einsatzbereitschaft
Verhaltensmuster für hohe Einsatzbereitschaft
Verhaltensmuster für normale Einsatzbereitschaft
Verhaltensmuster für gemäßigte Einsatzbereitschaft
Verhaltensmuster bei Krankheit

13.12 Spezielle Verhaltensmuster für Heraklit

Verhaltensmuster für heroische Einsatzbereitschaft
Verhaltensmuster für hohe Einsatzbereitschaft
Verhaltensmuster für normale Einsatzbereitschaft

13.13 Aktivitäten für alle Philosophen

Denken
Holen der Chopsticks
Essen
Zurückgeben der Chopsticks
Schlafen
Krankwerden
Altern

13.14 Spezielle Aktivitäten für Heraklit

Altern

13.15 Spezielle Aktivitäten für Sokrates

Holen der Chopsticks
Zurückgeben der Chopsticks
Altern

13.16 Spezielle Klasse für den Seins-Akt aller Seienden

13.17 Utility Klasse für die Verwaltung der Chopsticks

Anhänge

A Das Lambda-Kalkül

A.1 Syntax eines Lambda-Ausdrucks

A.2 Begriffe und Regeln des Lambda-Kalküls

Assoziativitätsregeln
Gebundene und freie Variable
Alpha-Konvertierung
Beta-Reduktion
Eta-Reduktion
Y-Kombinator

A.3 Beispiele für Beta-Reduktion

Lambda-Kalkül-Programmierung in Scheme-Codierung
Auszuwertende Lambda-Ausdrücke in Scheme-Codierung
Basis-Abstraktionen in Scheme-Codierung
Anwendung mit Beta-Reduktion

B Gültigkeitsbereich von Namen

B.1 Interpretation von Namen

Dynamic Scope
Static Scope
Global Scope
Local Scope

B.2 Auswirkung der Art der Symbolinterpretation auf die Programmierung

Auswirkung von „Dynamic Scope“ auf die Programmierung
Auswirkung von „Static Scope“ auf die Programmierung
Verdeutlichung der Unterschiede von „dynamic scope“ und „lexical scope“ anhand von Beispielen

C Ergänzungen zu OntoSimula

C.1 OntoSimula in Scheme

C.2 Philosophischer Hintergrund zu OntoSimula

Einleitung
Abbildung der Prinzipien in OntoSimula (Java)
Abbildung der Prinzipien in OntoSimula (Scheme)

Schlusswort

Biographische Daten zur Person des Autors

Verzeichnis der Fundamentalbegriffe

Abbildungsverzeichnis

Listings

Literaturverzeichnis

Index

Vorwort

Einleitung

Dieses Buch ist basiert auf dem 1032-seitigen Buch ‘Programmierung pur’(Siehe [16].), das in der 2. erweiterten Auflage von demselben Autor im Verlag S.Toeche-Mittler in Darmstadt im Jahre 2003 verffetlicht wurde. Die 1. Auflage erschien im Jahre 2002 unter derselben ISNB: 3-87820-108-7 .

Die Eigenschaften von A++ werden in verschiedenen Büchern in dieser Reihe vorgestellt, jedesmal mit einem anderen Schwerpunkt. Das vorliegende Buch wird unter Punkt 2 in der folgenden Liste beschrieben.

1. In A++ Die kleinste Programmiersprache der Welt[17] geht es darum, die theoretischen Grundlage dieser Sprache zu präsentieren und die Mächtigkeit von A++ aufzuzeigen.

2. In dem 2. Buch Programmieren lernen mit A++[20] ist auch eine Einführung in A++ enthalten, der Fokus des Buches liegt aber darauf zu zeigen, wie in den anwendungsorientierten Programmiersprachen Python und Java A++-orientiert programmiert werden kann.

In der englischsprachigen Ausgabe A++ The Smallest Programming Language in the World wird außerdem die Programmiersprache Perl und die A++-orientierte Programmierung in dieser Sprache erläutert.Siehe: [18]!

3. In dem 3. Buch A++ und systemnahe Programmiersprachen[19] liegt der Schwerpunkt darauf, aufzuzeigen, wie auch in den Programmiersprachen C und C++ A++-orientiert programmiert werden kann.

4. In dem 4. Buch Von A++ nach ARS++[21] wird schließlich eine Erweiterung von A++ vorgestellt, die einer neuen Programmiersprache entspricht (mit Compiler und virtueller Maschine) in der die Funktionalität von Python, Java, C++ und C enthalten ist. Dies ist mglich, da in ARS++ eine Schnittstelle zu den anderen Sprachen namens ARSAPI eingebaut ist.

Die Werkzeuge und Hilfsmittel zu diesem Buch werden in einem Download-Verzeichnis im Internet bereitgestellt. Siehe: 7.4 auf Seite 85.

Zweck des Buches

In diesem kleinen Büchlein, geht es primär darum an der Programmierung interessierten Leserinnen und Lesern ein Instrument vorzustellen, mit dem sie sehr schnell und sehr effizient Programmieren lernen können, ohne sich schon für eine der populären, voll-ausgebauten Programmiersprachen entscheiden zu müssen und ohne einen großen Kostenaufwand zu haben.

Dass es möglich ist, mit den Denkmustern von A++ in anderen Programmiersprachen produktiv sein zu können wird in diesem Buch gezeigt, indem nach einer Einführung in die Programmiersprachen Python und Java die A++-orientierte Programmierung in diesen zwei Sprachen vorgestellt wird.

Diese zwei ausgewählten Programmiersprachen gehören zu der Gruppe der höheren Programmiersprachen (’higher level languages’), die sich besonders fr anwendungsorientierte Programmierung eignen (application programming).

Im Unterschied dazu gibt es sogenannte systemnahe Programmiersprachen wie C und C++, die sich besonders fr Systemprogrammierung eignen (Betriebssysteme und Systemhilfsprogramme). Diesen Programmiersprachen im Zusammenhang mit A++ widmet sich das Buch A++ und systemnahe Programmiersprachen. (Siehe:[19]).

Theoretische Grundlagen von A++

Das Wesentliche der Programmierung

A++ ist die kleinste Programmiersprache der Welt, deren Sinn es ist einzig das Wesentliche der Programmierung darzustellen, und zwar in einer Form dass damit gearbeitet werden kann, dass man es einüben kann. So soll A++ hilfreich sein beim Erlernen des Programmierens ganz allgemein, aber auch beim Erlernen von konkreten Programmiersprachen.

Elementarteilchen der Programmierung

In A++ werden die Elementarteilchen der Programmierung in reinster Form sichtbar gemacht. Man kann diese gründlich studieren, den richtigen Umgang mit ihnen einüben und sich so die wichtigsten Rüstzeuge der Programmierung aneignen.

Vereinfachung der Programmierung

In dem Bemühen, Programmierung auf das Wesentliche zu reduzieren, geht es darum, Lernende zu bewahren, sich von einer Unzahl von Vorschriften und Regeln einer bestimmten Programmiersprache die Programmierung an sich vergraulen zu lassen.

Energien, die in den meisten Sprachen für die Beherrschung und das Einhalten der Syntax aufgebracht werden müssen, kommen in A++ der wichtigeren Aufgabe der logischen Bewältigung des zu lösenden Problems zugute.

Einfache, umfassende und mächtige Denkmuster

Es wird hier dank des Lambda-Kalküls eine Sicht der Programmierung gewonnen, die eine befreiende Wirkung hat. Das Denken wird aus den Niederungen des komplexen Regelwerks einer bestimmten Programmiersprache herausgeholt und heraufgehoben auf die Höhen eines einfacheren, umfassenderen und deshalb mächtigeren Denkens. Das Lambda-Kalkül bietet die theoretische Grundlage für eine solche Sicht.

Verallgemeinerung des Lambda-Kalküls

Der Name A++ ist eine Abkürzung von Abstraktion plus Referenz plus Synthese. Hiermit werden die drei Prinzipien von A++ benannt, die gleichzeitig ihr einziger Inhalt sind. Diese Prinzipien stellen eine Verallgemeinerung der Grundoperationen des Lambda-Kalküls von Alonzo Church dar. Das Lambda-Kalkül ist ein mathematisch-logisches System, das 1941 von dem Logiger Alonzo Church in seinem Buch: ‘The Calculi of Lambda Conversion’ der Welt vorgestellt wurde. Siehe hierzu unsere kurze Zusammenfassung im Anhang A auf Seite 277.

Während das Lambda-Kalkül der Funktionalen Programmierung ihre theoretische Grundlage liefert, ist A++ in der Lage eine theoretische Grundlage für die drei bekanntesten Paradigmen der Programmierung zu liefern, d.h. für die funktionale, die objekt-orientierte und die imperative Programmierung.

Verallgemeinerung der Grundoperationen des Lambda-Kalküls:

•Abstraktion: Etwas einen Namen geben

•Referenz: Auf etwas mit seinem Namen Bezug nehmen

•Synthese: Aus zwei oder mehr Dingen etwas Neues erzeugen

Die Primitiv-Operationen von A++ gehen inhaltsmäßig über die Grundoperationen des Lambda-Kalküls hinaus, indem ihnen in der Anwendung in einem Programm jedwede Einschränkung genommen wird.

Die Verallgemeinerung besteht darin, dass der Begriff der Abstraktion allgemeiner als im Lambda-Kalkül definiert wird, nämlich als ’etwas einen Namen geben’. Hinter dem Namen verbergen sich alle Details des Definierten. Eine solche Namensvergabe setzt eine explizite Namensdefinition voraus.

Im Lambda-Kalkül dagegen ist eine explizite Vergabe eines Namens für eine Lambda-Abstraktion bei deren Bildung nicht vorgesehen. Dort erfolgt sie lediglich implizit bei einer Synthese von Lambda-Ausdrücken.

Die Auswirkungen dieses zunächst als klein erscheinenden Unterschiedes sind gewaltig: Während ein Ausbau des Lambda-Kalküls immer in die Funktionalen Programmiersprachen mündet, können in A++ allgmeine Muster der Programmierung definiert werden, die sowohl auf die Funktionale Programmierung als auch auf die Objekt-orientierte und die Imperative Programmierung angewandt werden können.

Wer sich in seinem Programmieren von den Prinzipien in A++ leiten lässt, wird Programme erstellen, die nicht nur funktionieren, sondern die auch schön sind, Programme, bei denen Leser und Leserinnen mit Bewunderung die Abstraktionen und Synthesen nachempfinden und genießen können.

Erlernen von neuen Programmiersprachen

In ‘Programmierung pur’ wird erstmalig der Versuch unternommen, den Weg zum Erlernen der Programmiersprachen Scheme, Java, Python, C und C++ anhand der mittles A++ erarbeiteten Denkmuster aufzuzeigen. ‘Programmierung pur’ behandelt diese Thematik nicht nur theoretisch, sondern präsentiert umfangreiche Fallstudien, um den Bezug zur Programmierpraxis zu gewährleisten.

Adressatenkreis

Dieses Buch wendet sich ebenso wie ‘Programmierung pur’ an Programmierer und solche, die es werden wollen. Es möchte ihnen mit der speziellen Denkweise die Programmierung erleichtern, besonders auch das Erlernen neuer Sprachen. Mit der nahegelegten Sicht der Programmierung wird eine Sprachenunabhängigkeit gewonnen, ja man ist sogar offen für verschiedene Paradigmen der Programmierung. Mit der Erfahrung der gewonnenen Flexibilität ausgerüstet wird ein Programmierer oder eine Programmiererin mit mehr Freude und größerer Effizienz die Probleme der Programmierung meistern.

Das Buch wendet sich auch an Anfänger der Programmierung. Jedoch sollte ein großes Interesse für die Programmierung aufgrund einer persönlichen Eignung und Neigung vorhanden sein.

Zusammenfassend kann Zielgruppe des Buches wie folgt beschrieben werden:

Das Buch ist gedacht für Menschen, die einen Ausbildungsbedarf in den Grundlagen der Programmierung besitzen.

• Dies sind Studenten aller Fachrichtungen der Informatik sowie Studenten der Mathematik und Physik.

• Dies sind Lehrer und Schüler an Gymnasien, die in der Oberstufe Informatikunterrich gestalten oder an ihm teilnehmen.

• Dies sind ferner alle Angestellten in der Industrie, die sich, aus welchen Gründen auch immer, mit der Programmierung auseinandersetzen müssen.

•Programmierer, die bereits programmieren können, sich aber nicht scheuen, etwas Neues kennen zu lernen, kommen als potentielle Nutznießer dieses Büchleins gewiss ebenfalls in Betracht.

Danksagung

Danken möchte ich vor allem den Vielen, die in uneigennütziger Weise durch die Bereitstellung ihrer Software zur kostenlosen Nutzung zum Zustandekommen dieses Buches beigetragen haben.

Zu dieser frei verfügbaren Software gehört natürlich TEX, LATEX, teTeX, Linux, XFree86, vim, psutils, ghostview und die vielen Scheme-Implementierungen, ganz besonders GambitC und libscheme.

Dann gilt mein Dank natürlich ganz besonders Alonzo Church, dem wir das Lambda-Kalkül verdanken und Guy L. Steele mit Gerald J. Sussman, die dieses Lambda-Kalkül als Ausgangsbasis für die Entwicklung ihrer Programmiersprache Scheme genommen haben.

Der Dank erstreckt sich auch auf die im Literaturverzeichnis aufgeführten Autoren, die uns das Lambda-Kalkül näher gebracht haben.

Georg P. Loczewski

Groß-Zimmern, im Dezember 2002 bzw. im Mai 2018

Teil I

Grundlagen

Kapitel 1

Einführung

1.1 Konstitutive Prinzipien in A++

A++ steht für Abstraktion plus Referenz plus Synthese. Diese drei Begriffe entsprechen den sprachlichen Strukturelementen und den Grundoperationen in A++ und werden deshalb im nächsten Kapitel im Zusammenhang mit der Syntax der Sprache noch ausführlich behandelt.

Zu den konstitutiven Prinzipien, d.h. den Prinzipien, die A++ wesentlich zu dem machen, was es ist, gehören außerdem noch die Begriffe ‘Closure’ und ‘Lexical Scope’. Wir werden sie der Reihe nach definieren und beschreiben.

Abstraktion

FUNDAMENTALBEGRIFF 1 (ABSTRAKTION)

Abstrahieren bedeutet: Etwas einen Namen geben. Es besteht darin, etwas Komplexes zu behandeln, als wäre es etwas Einfacheres, indem Details ignoriert werden.

Eine solche Abstraktion wird auch als Lambda-Abstraktion bezeichnet, wenn mit ihr die Definition einer Funktion verbunden ist, die zwangsläufig zur Erzeugung einer ‘Closure’ mündet. Bezüglich des letzteren Punktes siehe weiter unten die Definition des vierten konstitutiven Prinzips.

Referenz

FUNDAMENTALBEGRIFF 2 (REFERENZ)

Auf etwas, das einen Namen erhalten hat, kann jederzeit mit diesem Namen Bezug genommen werden. Diese Bezugnahme nennen wir Referenz.

Im Zusammenhang mit der Referenz ist von großer Bedeutung auf welche Namen Bezug genommen werden kann. Dies führt zum letzten konstitutiven Prinzip von A++, dem Begriff des ‘Lexical Scope’.

Synthese

FUNDAMENTALBEGRIFF 3 (SYNTHESE)

Eine Synthese zu bilden bedeutet: Zwei oder mehrere Dinge (die selbst Ergebnis einer Abstraktion sind!) miteinander zu verknüpfen um etwas Neues (Komplexes) zu schaffen.

Der Begriff der Synthese entspricht weitgehend dem des Aufrufs einer Funktion oder der Abbildung, bzw. der Applikation.

Closure

Die Bildung einer Abstraktion ist in A++ nicht ein absolutes, von Allem losgelöstes Ereignis. Eine Abstraktion erfolgt immer in einem bestimmten Kontext, der somit wesentlich zu der gebildeten Abstraktion gehört. Die Lambda-Abstraktion wird zum Zeitpunkt ihrer Erzeugung mit ihrem Kontext oder ihrer Umgebung verbunden. Das Resultat dieser Verkapselung wird ‘Closure’ genannt. Eine Closure ist eine Art der Verkapselung wie wir sie in der Objekt-Orientierung finden. In der Objekt-Orientierung sind in einem Objekt Daten und Funktionen verkapselt, die Attribute des Objektes mit dessen Methoden gemäß ausdrücklicher Festlegung in der Klassendefinition oder im Aufbau des Konstruktors.

Bei einer Closure dagegen erfolgt diese Verkapselung nicht durch willkürliche, ausdrückliche Definitionen, sondern alles, was zum textlichen Umfeld einer Funktion gehört wird automatisch in diese Verkapselung einbezogen. Wir haben deshalb in ‘Programmierung pur’ das Bild einer Muschel1. als Symbol für eine Closure gewählt.

Somit können wir eine Closure wie folgt definieren:

FUNDAMENTALBEGRIFF 4 (CLOSURE)

Eine Funktion wird eine “Closure” genannt, wenn sie mit der sie umgebenden Menge der Daten und Funktionen fest verkoppelt ist. Die Variablen der geerbten Umgebung werden “freie Variable” und die Argumente der Funktion werden als “gebundene Variable” bezeichnet. Die in der Funktion definierten Variablen heissen “lokale Variable”. Alle Variable einer echten Closure haben unbegrenzte Lebensdauer.

Abbildung 1.1: Definition einer “closure”

Eine solche Funktion kann nur in der ihr eigenen Umgebung ausgeführt werden. Wir haben hier ein Beispiel der Verkapselung von ausführbarem Code mit den dazugehörigen Daten. So etwas Ähnliches finden wir wieder in der weiter unten beschriebenen Objekt-Orientierung.

Eine “closure” kann man sich nach ihrer Definition folgendermaßen vorstellen: Siehe hierzu Abbildung 1.1. Die zwei Kreise nebeneinander sind das Symbol für eine “closure”. Diese Diagrammtechnik wurde eingeführt von Harold Abelson und Gerald Jay Sussman in ihrem legendären SICP-Buch, d.h. dem offiziellen Lehrbuch der Informatik am Massachusetts Institute of Technology mit dem Titel: Structure and Interpretation of Computer Programs. Siehe hierzu im Literaturverzeichnis [1].

An den Programmtext fest gekoppelt ist die Umgebung des Programms, in dem die “closure” definiert wurde ( “lexical scope”). Diese Heimatumgebung der “closure” hat in allen folgenden Diagrammen das Kennzeichen ’<umgebung 1>’.

Zum Zeitpunkt der Ausführung der Funktion sieht die Sache etwas anders aus. Der Funktion wird ein neuer Umgebungsbereich zugewiesen (“environment frame”), der allerdings wiederum mit der ursprünglichen Umgebung der “closure” verknüpft ist. Dieser neue Umgebungsbereich enthält die Argumente der Funktion und die in ihr definierten lokalen Variablen. In den folgenden Diagrammen trägt sie das Kennzeichen ‘<umgebung 2>’. Siehe hierzu Abbildung 1.2 auf der nächsten Seite!

Lexical Scope

Es kann auf bereits definierte Abstraktionen über Namen Bezug genommen werden. Auf welche Namen an welcher Stelle im Programm Bezug genommen werden kann, definiert der sogeannte Scope in einer konkreten Programmiersprache. Es gibt drei Muster nach denen die Gültigkeit von Namen in Programmteilen geregelt ist:

Lexical Scope oder Static Scope: In diesem Schema gelten die Namen nur in dem Bereich, in dem sie definiert sind. Der Gültigkeitsbereich ist direkt aus dem Programmtext ersichtlich, woher der Name “lexical scope” rührt.

Wir definieren deshalb:

Abbildung 1.2: Aufruf einer “closure”

FUNDAMENTALBEGRIFF 5 (LEXICAL SCOPE)

Namen gelten nur in den Funktionen, die die Namensdefinition enthalten, bzw. in solchen, die innerhalb dieser Funktion als verschachtelte Funktionen definiert wurden.

Mit dem ‘lexical scope’ kann wie in der Programmiersprache Algol ein ‘dynamic extent’ verbunden sein, oder wie in Common-Lisp und in Scheme der ‘indefinite extent’.

Letzerer bedeutet, dass alle Variablen unbegrenzte Lebensdauer haben. Die unbegrenzte Lebensdauer wird allerdings dadurch eingeschränkt, dass Variable, die von nirgendwoher mehr im Programm erreicht werden können, als Müll vom Garbage-Collector beseitigt werden.

Closures können auch gesehen werden als Funktionen mit ‘lexical scope’ und ‘indefinite extent’.

Dynamic Scope: Eine Variable kann von überallaus im Programm direkt mit ihrem Namen angesprochen werden. Dynamic Scope ist von McCarthy ursprünglich in Lisp eingeführt worden, wird aber inzwischen wegen gewaltiger Nachteile in modernen Lisp-Dialekten nicht mehr oder nur bedingt verwendet. McCarthy selbst hat eingesehen, dass es ein Design-Fehler war, dynamic scope in Lisp zu verwenden.2

GlobalundLocalScope: In diesem Schema hat eine Variable entweder ‘global’ oder ‘local scope’. Im ersten Falle bedeutet das, dass eine Variable überall Gültigkeit besitzt. Im zweiten Fall gilt eine Variable nur in der Funktion, in der sie definiert wurde, ohne dass sich diese Gültigkeit auf tiefere Ebenen fortpflanzen würde. Dieses System wird momentan noch in der Programmiersprache Python verwendet.

Im nächsten Kapitel wird das sprachliche Gewand eingeführt, in das wir diese drei Operationen kleiden werden, um mit ihnen programmieren zu können.

1Das englische Wort für Muschel ist bekanntlich ‘clam’. Bei uns hat ‘clam’ noch sinnvoller Weise eine andere Bedeutung, nämlich: ‘c-lambda-abstraction’. So bezeichnen wir in ARSAPI eine Lambda-Abstraktion in C. Siehe hierzu Abschnitt 8.2 auf Seite 88

2siehe Seite 180: R.Wexelblat(ed.), History of Programming Languages, Academic Press, New York, 1981.

Kapitel 2

Sprachdefinition

2.1 Syntax und Semantik von A++

Um die Syntax von A++ zu definieren, werden wir die EBNF-Notation verwenden.

Zuerst folgt die Erklärung der EBNF-Notation selbst:

EBNF-Notation:

• bedeutet „oder“

• [ . . . ] eckige Klammern bedeuten optional.

• { . . . } bedeutet „0 oder n-mal“.

• ’ . . . ’ kennzeichnet Text, der wörtlich zu nehmen ist.

• ( . . . ) runde Klammern können zur Gruppierung benutzt werden.

• <. . . > Abkapslung eines Begriffs.

• empty bedeutet die leere Menge.

Syntax von A++ in EBNF-Notation:1

Anmerkungen zur Syntax:

Zur Definition der Abstraktion in (2)

• Die erste Alternative in der Definition bezieht sich auf die allgemeine Form der Namensvergabe.

• Die zweite Alternative bezieht sich auf das, was der Namensvergabe normalerweise vorausgeht, die eigentliche Abstraktion. Die Namensvergabe ist nur der letzte Schritt.

– Es gibt auch anonyme Lambda-Abstraktionen, bei denen die Namensvergabe als überflüssig weggelassen wird.

– Der Definition einer anonymen Lambda-Abstraktion kann auch als Definition einer Funktion angesehen werden.

Zur Definition der Synthese in (4)

Eine Synthese gemäß obiger Definition wird auch oft als Funktionsaufruf oder als Abbildung (Applikation) bezeichnet.

2.2 Beispiele zur Syntax von A++