Du befindest dich hier: FSI Informatik » Prüfungsfragen und Altklausuren » Hauptstudiumsprüfungen » Lehrstuhl 2 » Principles of Programming Languages   (Übersicht)

Principles of Programming Languages

Prüfer: Ronald Veldema
Beisitzer: Andreas Kumlehn

Vorbereitung

Zur Vorbereitung bin ich alle Folien durchgegangen und habe sie zusammengefasst. Im Anschluss habe ich versucht, sie jedem zu erklären, der sie nicht hören wollte ;) Ein paar mal habe ich zudem versucht, etwas Haskell oder Prolog aus den Folien blind nachzuprogrammieren, um da nicht ganz blank dazustehen.

Allgemeine Modalitäten

Stift und Papier werden gestellt. Habe ich aber erst ab der Aufgabe zur funktionalen Programmierung benötigt. Es war wirklich nicht schlimm, mal etwas nicht zu wissen, aber mich persönlich hat es doch sehr nervös gemacht. Wie auch in anderen Prüfungsprotokollen beschrieben, gibt es teilweise sehr starke Themensprünge, sei es dadurch, dass man selbst bereits etwas angesprochen hatte, oder man einfach genug gesagt hatte und ein nächstes Themengebiet angegangen wurde.

Prüfungsablauf

F: Welche Sprache kannst du am besten?
A: C

F: Ist C typorthogonal?
A: Nein
Anm.: Gab eine kleine Diskussion darüber, ob das wirklich so ist. Habe dann Typorthogonalität allgemein erklärt (was wohl auch in Ordnung war). Dass C nicht typorthogonal ist, sieht man übrigens an diesem Beispiel (das nicht kompilieren wird):

char[] array_returning_function(void) {
	return NULL;
}

In C kann also nicht jeder Typ (im Beispiel char[]) überall eingesetzt werden.

F: Sind structs und Unions das gleiche?
A: Nein, die Member eines structs liegen hintereinander im Speicher, bei Unions liegen sie „aufeinander“, sodass beim Zugriff auf unterschiedliche Member unter Umständen die gleichen Werte unterschiedlich interpretiert werden.

F: Was ist eine polymorphe Funktion/Methode?
A: Erst polymorphen Aufruf erklärt. Wurde verbessert: Funktion, die mit beliebigen Parametern aufgerufen werden kann.

F: Was ist der Unterschied zwischen Templates und Generics?
A: Generics: Typauslöschung erklärt, Templates: Typersetzung erklärt

F: Was sind Reflections?
A: Zur Laufzeit Compilezeitinformationen auslesen, bedingt auch ändern (z.B. Sichtbarkeit, nicht aber Methodeninhalte).

F: Kann man mit Reflections Generics auslesen (immerhin Compilezeitinformationen)?
A: Nein, wegen Typauslöschung.

F: Was ist Dependency Injection?
A: ???
Anm.: Im Prinzip das Factory Pattern

F: Was ist Aspektorientierung?
A: Funktionalitäten = Aspekte, je nach Bedarf zusammenweben („in Klassen slicen“, „an Joinpoints anbringen“, …). Meist eine vorhandene Grundfunktionalität. Beispiel genannt.

F: Mal etwas zu verteilten Sprachen: Verteilter Speicher und Message Passing?
A: Das eine kann auf das andere abgebildet werden (und muss im verteilten Fall auch so sein). Geänderter Speicher wird als Nachricht versendet.

F: Und was gibt es dafür in Programmiersprachen?
A: Channels erklärt, dabei gleich noch auf RPCs (vgl. Java-RMI) und Rendezvous (vgl. Ada) eingegangen.

F: Was ist transaktionaler Speicher?
A: CAS im Großen, Generationenzähler verwenden, um zeitgleiche Änderungen zu bemerken, Änderungen durchführen, atomar Generationenzähler vergleichen und zurückschreiben… Eventuell Roll-Back nötig (besonders bei globalem Zustand). (Vgl. Datenbanktransaktionen)

F: Und was sind Monitore?
A: Meist in Programmiersprachen eingebaute Synchronisationsmöglichkeit, die bei ausschließlicher Verwendung ohne Deadlocks ist und kritische Abschnitte schützen kann.

F: Nun zu funktionaler Programmierung: In einer Liste hintereinanderkommende Duplikate entfernen. Bitte Patternmatching verwenden.
A: Pseudocode reicht völlig aus

simp [X:[Y:Z]] = simp [X:[Y:Z]];
simp [X:[X:Z]] = simp [X:Z];
simp []        = [];

F: Und das ganze jetzt mit logischer Sprache.
A: Auch hier kann man Pseudocode voll auskosten und es fast genauso machen wie bei der funktionalen Umsetzung.

simp [X:[Y:Z]] A :- A is simp [X:[Y:Z]];
simp [X:[X:Z]] A :- A is simp [X:Z];
simp []        A :- A is [];

F: Eine kleine Aufgabe: Wer bei McDonald's isst, ist reich. Ronald und Andreas essen bei McDonald's.
A: noch mehr Pseudocode

% Fakten:
mcdonalds(andreas).
mcdonalds(ronald).

% Regeln:
reich(X) :- mcdonalds(X).

F: Wie sieht die Anfrage aus, wenn man wissen will, wer reich ist?
A: Unifikation, Backtracking, etc.

?- reich(X).
X = andreas.
X = ronald.

F: Was ist der Unterschied zu Datalog?
A: (fast mit Fuzzy Prolog verwechselt); vereinfachtes Prolog, sucht immer alle Lösungen

F: Wenn du eine eigene Sprache entwickeln willst, was brauchst du in deine Spezifikation?
A: Lexikographische Informationen, Grammatik, Semantik.

F: Bitte die Grammatikregel für ein while Statement (for Statement war wohl in vorherigen Prüfungen dran) aufschreiben.
A:

while_stmt ::= "while" cond block

F: Nun die Semantik mit einer Attributgrammatik beschreiben.
A: ??? Mit Hilfe (und sehr erstaunt, dass das so einfach sein soll):

while_stmt ::= a=cond b=block { while a b }

F: Jetzt mit operationaler Grammatik.
A: Andere/einfacherer Sprache verwenden, z.B. „Pseudo-Assembler“

	goto cond;
loop:
	block
cond:
	if <cond> goto loop

F: Und mit axiomatischer Grammatik.
A: Vorbedingungen und Nachbedingungen, (auf Nachfrage noch negierte Bedingung als Nachbedingung hinzugefügt)

V: Vorbedingung

{V}
while_stmt ::= "while" cond block
{block(V) and not cond}

Anm.: Es hat gereicht, block nur einmal auf V anzuwenden, aber natürlich wird das ja für jeden Schleifendurchlauf passieren (also auf die Zwischenzustände).