Konzepte der Programmiersprachen

Werbung
Konzepte der Programmiersprachen
Sommersemester 2012
Torsten Görg
5. Übungsblatt
Besprechung am 27. Juni 2012
http://www.iste.uni-stuttgart.de/ps/lehre/ss2012/v-konzepte.html
Aufgabe 5.1: Seiteneffekte
1. Welche Eigenschaft muss eine Funktion f in Modula-2 haben, damit in einem
Programmstück wie
IF f(x) <> f(x) THEN WriteString ("ungleich")
ELSE WriteString ("gleich")
END;
die Meldung ungleich ausgegeben wird?
2. Weshalb ist das Konstrukt y = (x = 2 * x) + (x = x + 1); in C verboten?
Probieren Sie aus, ob Ihr Compiler hier Warnungen oder Fehlermeldungen ausgibt, stellen sie dafür möglichst „kleinliches“ Verhalten ein.
3. Seiteneffekte sind nur möglich, wenn es Variablen (oder allgemeiner, Objekte)
gibt, die einen veränderbaren Zustand haben.
Haben Seiteneffekte und veränderbare Zustände Vorteile oder sollten sie in einer
„guten“ Programmiersprache generell verboten sein? Welche Zusammenhänge
bestehen mit der funktionalen Programmierung und der objekt-orientierten Programmierung?
Aufgabe 5.2: Konzepte funktionaler Sprachen
1. Welche funktionalen Sprachen kennen sie? Welche davon setzen das funktionale Paradigma in einer reinen Form um? Wie und wo werden bei den nicht rein
funktionalen Sprachen imperative Sprachmittel eingebaut?
2. Welche Konzepte muss eine rein funktionale Sprache mindestens haben, um Turing-vollständig zu sein?
Welche weiteren Konzepte umfassen viele funktionale Sprachen in der Regel darüber hinaus noch?
1
Aufgabe 5.3: Rekursive Funktionen auf rekursiven Datenstrukturen
In funktionalen Sprachen führen oft rekursive Funktionen Berechnungen auf rekusiv
definierten Datenstrukturen (z.B. Listen) durch.
Untersuchen sie folgenden CommonLisp-Programmcode (frei verfügbare CommonLispCompiler und weiterführende Informationen zu CommonLisp erreichen Sie z.B. über
http://www.clisp.org/):
(01)
(02)
(03)
(04)
(05)
(06)
(07)
(08)
(09)
(10)
(11)
(12)
(13)
(14)
(15)
(16)
(17)
(defun member (element searchList)
(cond
((null searchList) nil)
((eq element (car searchList)) t)
(t (member element (cdr searchList)))
)
)
(defun mystery (list1 list2)
(cond
((null list1) ’())
((member (car list1) list2)
(cons (car list1)
(mystery (cdr list1) list2)))
(t (mystery (cdr list1) list2))
)
)
Was berechnet die Funktion mystery für zwei als Parameter eingehende Listen list1
und list2 ?
2
Aufgabe 5.4: Funktionale Umsetzung von Algorithmen
Gegeben sei folgender Code in der imperativen Programmiersprache Pascal zur Tiefensuche in einem Graphen, die in Form von Adjazenzlisten in adj vorliegt:
(01)
(02)
(03)
(04)
(05)
(06)
(07)
(08)
(09)
(10)
(11)
(12)
(13)
(14)
(15)
(16)
(17)
(18)
(19)
procedure dfs
var id, k : integer;
val : array[1..maxV] of integer;
procedure visit (k : integer)
var t : link;
begin
id:=id+1; val[k]:=id;
t:=adj[k];
while t<>nil do begin
if val[t^.v]=0 then visit (t^.v);
t:=t^.next
end
end;
begin
id:=0;
for k:=1 to maxV do val[k]:=0;
for k:=1 to maxV do
if val[k]=0 then visit (k);
end;
1. An welchen Stellen dieses Programmfragments werden imperative Sprachmittel
verwendet, die so nicht direkt in eine funktionale Lösung übernommen werden
können?
2. Formen sie den vorliegenden Code in eine äquivalente funktionale Implementierung um. Benutzen sie dazu eine funktionale Programmiersprache ihrer Wahl
(z.B. Haskell).
Aufgabe 5.5: List Comprehensions
In Haskell können die in einer Liste enthaltenen Werte mit einer Listenabstraktion
(engl. list comprehension) ausgedrückt werden, indem man eine Rechenvorschrift angibt, die die Elemente der Liste generiert. Was berechnet die folgende, auf Listenabstraktionen basierende Haskell-Funktion mystery2 für eine als Funktionsparameter
übergebene Liste?
mystery2 [] = []
mystery2 (h:t) = mystery2 [b | b <- t, b < h]
++ [h] ++
mystery2 [b | b <- t, b > h]
3
Aufgabe 5.6: Typ-Inferenz in funktionalen Sprachen
Betrachten Sie folgendes Programmfragment in einer funktionalen Sprache:
letrec length = λl. if null l
then 0
else 1 + length (tail l)
in ...
Vorgegeben seien folgende Typen:
0, 1, . . . : int
+ : int → int → int
if/then/else : bool → T → T → T
head : T list → T
tail : T list → T list
null : T list → bool
1. Geben Sie ein äquivalentes Programmfragment für die Definition von length in
Haskell-Syntax an.
2. Stellen Sie die Definition von length durch einen Syntaxbaum dar, in dem Sie
auch für λ-Abstraktion und Funktionsanwendung jeweils einen Knoten einfügen.
Leiten Sie dann für jeden Knoten im Syntaxbaum durch Inferenz den Typ her. Ist
die Definition typkorrekt?
3. Ersetzen Sie in der Definition von length den Aufruf von tail durch einen
Aufruf von head. Ist diese neue Definition typkorrekt? Falls es einen Unterschied
zu Teilaufgabe 2 gibt, wo tritt dieser in der Inferenz auf?
4
Herunterladen