Dagens föreläsning Programmering i Lisp. - Bindning av variabler (avs 14.6) fria variabler statisk/lexikalisk och dynamisk bindning

Relevanta dokument
Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

Dagens föreläsning Programmering i Lisp Fö 5

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 2

Dagens föreläsning. Diverse Common Lisp. Konstanter, parametrar, globala variabler

Imperativ programmering. Imperativ programmering konstruktioner i Lisp. Datastrukturer (kap ) arraystruktur poststruktur

Tentamen i. TDDC67 Funktionell programmering och Lisp

TDDC74 Programmering, abstraktion och modellering. Tentamen

Rekursiva algoritmer sortering sökning mönstermatchning

TDDC74 Programmering, abstraktion och modellering. Tentamen

I dag: Blockstruktur, omgivningar, problemlösning

Uppgift 4A - Definition av enkla funktioner

Uppgift 6A - Frekvenstabell

TDDC74 Programmering, abstraktion och modellering. Tentamen

TDDC74 Lab 04 Muterbara strukturer, omgivningar

TENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13:15

Tentamen i. TDDA 69 Data och programstrukturer

TDDC74 Programmering, abstraktion och modellering. Tentamen

Dagens föreläsning Programmering i Lisp Fö 7. Sammanfattning funktionell programmering Exempel på funktionella programspråk

allt.cl Page 1 of 17 Date: torsdag 7 december 2006

TDDC74 Programmering: Abstraktion och modellering Datortenta

Tentamen i Introduktion till programmering

TDDC74 Programmering: Abstraktion och modellering Tenta, kl 14 18, 11 juni 2014

Omgivningar. Omgivningar är viktiga eftersom de avgör vilka namn som är synliga och därmed dessas innebörd och de värden som är förknippade med dem.

Dagens föreläsning. Modeller för programmeringsspråk. - Olika modeller programspråk Interpretator - kompilator. - Syntax - semantik.

Imperativ och Funktionell Programmering i Python #TDDD73. Fredrik Heintz,

Deklarationer/definitioner/specifikationer

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

TDDC74 - Lektionsmaterial C

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

TDDC74 Programmering: Abstraktion och modellering Tentamen, lördag 29 augusti 2015, kl 8 12

Objektorientering: Lagring, räckvidd och livstid

Idag: Par och listor. Symboler. Symboler används för att uttrycka icke-numeriska data såsom namn, adress, bilregisternummer, boktitel, osv.

TDDD78 Objektorientering: Lagring och livstid

Idag: Par och listor. Scheme. DA2001 (Föreläsning 6) Datalogi 1 Hösten / 29

OMTENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13: 15

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 08-12

TDDC74 Programmering: Abstraktion och modellering Dugga 2, , kl 14-16

TDDC74 Programmering: Abstraktion och modellering Dugga 2, , kl 17-19

TDDC74 Programmering, abstraktion och modellering DUGGA 2

Lösningsförslag. TDDC74 Programmering: Abstraktion och modellering. Dugga 3 (provkod TEN1), Tid: kl 14-16, Datum:

Objektorientering: Lagring och livstid

Föreläsning 3-4 Innehåll

Två fall: q Tom sekvens: () q Sekvens av element: (a b c) ; (sum-rec '(2 4 6)) = 12. q Första elementet uppfyller vissa villkor: (2 a b c)

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

Språket Python - Del 2 Grundkurs i programmering med Python

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

TDDC74 Programmering, abstraktion och modellering DUGGA 3

Programmering I Tobias Wrigstad fredag, 2009 augusti 28

Objektorienterad Programmering (TDDC77)

Problemlösning och funktioner Grundkurs i programmering med Python

Command line argumenter. Objektorienterad Programmering (TDDC77) Vad blir resultatet? Nu då? Ahmed Rezine. Hösttermin 2016

BEGREPP HITTILLS FÖRELÄSNING 2 SAMMANSATTA UTTRYCK - SCHEME DATORSPRÅK

Övningsuppgifter kapitel 8

Lambdas. (och fler design patterns) Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2017

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Programmering i C++ EDA623 Objektorienterad programutveckling. EDA623 (Föreläsning 5) HT / 33

Grundkurs Programmering

TDDC74 Programmering: Abstraktion och modellering Datordugga 2 - exempel

GPT föreläsning 8. Förra veckan: Man kan ta tiden på en sorterad teckensträng Förra gången: Problemlösning på lägre nivå kan sortera funktioner

Funktioner. Linda Mannila

Att förstå hur man konstruerar modulära program Att kunna skapa nya funktioner Att förstå hur data skickas mellan funktioner

Funktionell programmering DD1361

Datalogi, grundkurs 1

TDDC74 Programmering: Abstraktion och modellering Dugga 3, kl 14 16, 25 mars 2015

Våra enkla funktioner eller procedurer

Datalogi, grundkurs 1. Lösningsförslag till tentamen

Outline. I Vi kan lätt göra samma sak för fyra variabler... I Hur gör vi för 400 inlästa värden? I Ofta behöver man flera likadana variabler

Design av en klass BankAccount som representerar ett bankkonto

Dynamiskt minne. Vad är dynamiskt minne Motivering Hur gör man i C Övningar

FÖRELÄSNING 2, TDDC74, VT2018 BEGREPP PROBLEMLÖSNING MED HJÄLP AV FALLANALYS PROBLEMLÖSNING MED HJÄLP AV REKURSION

Kopiering av objekt i Java

Funktionens deklaration

TDDC77 Objektorienterad Programmering

SCB :-0. Uno Holmer, Chalmers, höger 2 Ex. Induktiv definition av lista. // Basfall

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

TDP002 - Imperativ programmering

Java, klasser, objekt (Skansholm: Kapitel 2)

Sätt att skriva ut binärträd

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

Funktioner. TDDD73 Funktionell och imperativ programmering i Python Föreläsning 8. Peter Dalenius Institutionen för datavetenskap

Idag: Dataabstraktion

TDDC74 Programmering, abstraktion och modellering DUGGA 1

Typsystem. Typsystem... Typsystem... Typsystem... 2 *

Numeriska Metoder och Grundläggande Programmering för P1, VT2014

Typsystem. DA2001 (Föreläsning 23) Datalogi 1 Hösten / 19

Användarhandledning Version 1.2

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Om att lära sig programmera. Föreläsning 1-2 Innehåll.

Grundläggande datalogi - Övning 1

Inledande matematik för I1. MVE011 läsperiod Matlab vecka 2 övningsuppgifter

Datalogi, grundkurs 1. Lösningsförslag till tentamen

Föreläsning 4 Programmeringsteknik DD1310. Felhantering. Syntax. try och except är reserverade ord som används för hantering av exekverings fel.

Objektorienterad programmering

Planering av ett större program, del 2 - for och listor. Linda Mannila

Objektorienterad Programmering (TDDC77)

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

Transkript:

1 Dagens föreläsning Programmering i Lisp - Block, räckvidd - Bindning av variabler (avs 14.6) fria variabler statisk/lexikalisk och dynamisk bindning - Felhantering (kap 17) icke-normala återhopp catch och throw unwind-protect - Lexical closure (kap 19) generatorer objektorienterad programmering

2 Det finns två olika slags omgivningar: Statiska / lexikala omgivning. Hur ser läget ut i koden då funktionerna definieras. Dynamiska omgivningen. Hur ser läget ut då vi exekverar programmet. Många konstruktioner i programspråken kan tolkas relativt en av dessa två omgivningar eller båda. Vi skall studera: Fria variabler, hur man finner värdet på dessa i båda dessa omgivningar. Icke-normala återhopp, dvs hur man kan avsluta beräkningen och återgår till andra positioner i programmet, t ex för felhantering. Funktioner / lexical closure. Funktioner definieras i en omgivning och kan sedan som dataobjekt lämna denna omgivning. Ger en förklaring varför vi använder function i stället för quote för funktionsobjekt. Detta kan utnyttjas till intressanta konstruktioner t ex generatorer, och objektorientering.

3 Bindning av variabler Blockstruktur - räckvidd (scope) x l e f g (lambda (e) (+ e x)) x h (defun f (x) (labels ((g (l) (cons x (mapcar # (lambda (e) (+ e x)) l))) (h (x) (+ 2 x))) (g (cons (h x) (2 3)))))

4 Bindning av variabler Fri variabel (defun f (x) (+ x y)) Statisk (lexikalisk) bindning: (defun g (y z) (labels ((f (x) (+ x y))) (f z))) (g 10 20) => 30 En fri variabel slås upp i närmast omslutande block (följer blockstrukturen). Entydigt bestämd från programkoden. Vanligen standard i programspråk.

5 Dynamisk bindning: (defun f (x) (declare (special y)) (+ x y)) 1 (defun g (y z) (declare (special y)) (f z)) Senast bundna y på stacken. Följer exekveringen av programmet. Den fria variabeln är ej entydigt bestämd. 2 (defun h (x y z) (declare (special y)) (+ x (f z))) värdet på y? värdet på y? f f x 20 x 3 h g x 1 y 10 y 2 z 20 z 3 Anrop fall 1 Anrop fall 2

6 Det kan bli problem med att komma åt andra funktioners lokala variabler och frågan är hur man kan lösa detta. Detta kan vara ett problem i projektarbetet. Två mer motsatta modeller. Hela programmet/funktionen bildar en enhet genom blockstruktur: Programmet består av egna enheter/funktioner:

7 Vi illustrerar problemet med ett litet exempel ur läroboken sid 275. Med kommandon (lagra och hämta) läggs personer till på en stack och kan tas bort. Skulle t ex kunna vara kommandon i en dialog (men är ej viktigt för att illustrera problemet) (setq några-kommandon ((lagra. anna) (lagra. karin) (hämta) (lagra. anders) (lagra. eva) (hämta) (hämta) (lagra. peter) (hämta))) (person-bearbetning några-kommandon) => (peter anders eva karin)

8 Exempel A Alla globala funktioner (defun person-bearbetning (kommandon) (let ((*person-stack* ()) (resultat ())) (mapc # (lambda (kommando) (case (car kommando) (lagra (lagra (cdr kommando))) (hämta (setq resultat (cons (hämta) resultat)))))) kommandon) resultat)) (defun lagra (person) (setq *person-stack* (cons person *person-stack*))) (defun hämta () (prog1 (first *person-stack*) (setq *person-stack* (rest *person-stack*)))) CL-USER(4): (person-bearbetning några-kommandon) Error: Attempt to take the value of the unbound variable *PERSON-STACK*. Funktionen lagra kan ej komma åt en lokal variabel i person-bearbetning. Båda funktionerna är definierade på samma nivå.

9 Exempel B Strukturera med lokala funktioner (defun person-bearbetning (kommandon) (let ((*person-stack* ()) (resultat ())) (labels ((lagra (person) (setq *person-stack* (cons person *person-stack*))) (hämta () (prog1 (first *person-stack*) (setq *person-stack* (rest *person-stack*))))) (mapc # (lambda (kommando) (case (car kommando) (lagra (lagra (cdr kommando))) (hämta (setq resultat (cons (hämta) resultat))))) kommandon) resultat))) CL-USER(5): (person-bearbetning några-kommandon) (PETER ANDERS EVA KARIN) Åtkomlig genom räckviddsregeln = närmast omslutande block.

10 Exempel C Globala funktioner och global variabel (defun person-bearbetning (kommandon) (let ((*person-stack* ()) (resultat ())) (mapc # (lambda (kommando) (case (car kommando) (lagra (lagra (cdr kommando))) (hämta (setq resultat (cons (hämta) resultat)))))) kommandon) resultat)) (defun lagra (person) (setq *person-stack* (cons person *person-stack*))) (defun hämta () (prog1 (first *person-stack*) (setq *person-stack* (rest *person-stack*)))) (setq *person-stack* ()) CL-USER(6): (person-bearbetning några-kommandon) (PETER ANDERS EVA KARIN) CL-USER(7): *person-stack* (ANNA) Man vill undivka globala variabler. man kan t ex bara ha en personstack. Man kanskse vill kunna ha flera.

11 Exempel D. Globala funktioner och lokal variabel med dynamisk bindning (defun person-bearbetning (kommandon) (let ((*person-stack* ()) (resultat ())) (declare (special *person-stack*)) (mapc # (lambda (kommando) (case (car kommando) (lagra (lagra (cdr kommando))) (hämta (setq resultat (cons (hämta) resultat)))))) kommandon) resultat)) (defun lagra (person) (declare (special *person-stack*)) (setq *person-stack* (cons person *person-stack*))) (defun hämta () (declare (special *person-stack*)) (prog1 (first *person-stack*) (setq *person-stack* (rest *person-stack*)))) CL-USER(8): (person-bearbetning några-kommandon) (PETER ANDERS EVA KARIN) Genom ordningen på anropen så kommer vi åt en tidigare införd lokala variaberl som fortfarande finns kvar på.

12 Icke-normala återhopp används oftast vid felhantering. Normalt går man in i en funktion, gör alla beräkningar och avslutar då allt är klart. Men vi kan avsluta funktionen/blocket i förtid Återhopp inom statisk omgivning: return / return-from Återhopp inom dynamisk omgivning: catch / throw Möjlighet att återställa sidoeffekter med: unwind-protect

13 Återhopp inom statisk omgivning (defun f (x) namn på block (labels ((g (y) resultatuttryck (when (< y 0) (return-from f neg)) (+ y 10))) (print (+ (g x) 1)))) Vid fel sker direkt uthopp med return-from ur först g och sedan f och ger värdet av resultatuttrycket som värde av anropet till f. (defun h (x) (let ((value (f x))) (if (eq value neg) 0 value))) (h -5) ; fel -> ingen utskrift => 0 (h 5) ; ok öka 5 med 10 och sedan 1 16 ; utskrift =>16

14 Återhopp inom dynamisk omgivning (catch catch-label uttryck) (throw catch-label värdeuttryck) catchlabel uttryck att beräkna (defun p (x) (let ((value (catch error (fn x)))) (if (eq value arg-error)... fel har uppstått...... bearbeta värde...))) (defun fn (x)... (throw error arg-error)... )) catchlabel resultatuttryck

15 Exempel Vi skall hitta elementen före ett givet element på en lista. (first-part x (a b x c)) = > (a b) Normalfallet är att elementet skall finnas på listan, men man vill lägga in en kontroll om man inte hittar elementet och i så fall signalera någon typ av fel. Normal definition (utan felkontroll) (defun first-part (x l) (cond ((eq x (first l)) ()) (t (cons (first l) (first-part x (rest l))))) Om ett fel uppstår så har vi gjort ett stort antal rekursiva anrop och vill inte backa och returnera på ett vanligt sätt, utan direkt kunna återgå till ett högre anrop.

16 Vi vill signalera något felvärde, t ex element-not-in-list (first-part y (a b x c)) = > element-not-in-list Vi strukturer problemet i två funktioner. (defun first-part (e l) (catch element-error (first-part-hlp e l))) (defun first-part-hlp (e l) (cond ((endp l) (throw element-error element-not-in-list)) ((eq e (first l)) ()) (t (cons (first l) (first-part-hlp e (rest l))))) Anropsstruktur: first-part -> first-part-hlp -> first-part-hlp -> first-part-hlp -> first-part-hlp -> first-part-hlp -> direkt återhopp till first-part

17 Alternativt ett statiskt hopp om first-part-hlp görs lokal. (defun first-part (e l) (labels ( (first-part-hlp (e l) (cond ((endp l) (return-from first-part element-not-in-list)) ((eq x (first l)) ()) (t (cons (first l) (first-part-hlp e(rest l)))))) (first-part-hlp e l))) Direkt uthopp, dvs lämnar alla anrop, som ej ännu har slutförts.

18 Dynamiskt återhopp Följer den dynamiska omgivningen, dvs följer i tur och ordning funktionsanropen (som ligger på stacken) och ser om det finns en catch-label med givet namn. (defun p (x) (labels ((q (y)... (throw error felkod)...) (r (x)... (catch error (q 20))...)) )) (catch error (r 10))... (catch error (q))

19 Återställning (unwind-protect uttryck återställningsuttryck) Exempel: (unwind-protect (bearbeta-data fil) (when (fil-är-öppen? fil) (stäng fil)))

20 Funktionsobjekt - Lexical closure Vad händer med fria variabler om en funktion returneras som värde från sin statiska omgivning? y (lambda (x) (+ x y)) returneras som värde Med function sparas den statiska omgivningen, dvs fria variabler (variabeln y ovan) behåller sitt ursprungliga värde.

21 Man skapar ett sk lexical closure. Sparade värden kan även ändras! Vad kan det användas till? Man kan se en sådan funktion / lexical closure som ett objekt som bibehåller ett tillstånd. När man returnerar från en vanlig funktion försvinner ju alla bindningar av parametrar och lokala variabler. y - 100 (lambda (x) (+ x y))

22 Generatorer - Skapa flip-flop Funktionen returnerar 0, 1, 0, 1 etc (defun skapa-flip-flop () (let ((tillstånd 0)) # (lambda () (prog1 tillstånd (if (eq tillstånd 0) (setq tillstånd 1) (setq tillstånd 0)))))) (setq f1 (skapa-flip-flop)) (setq f2 (skapa-flip-flop)) (funcall f1) => 0 (funcall f1) => 1 (funcall f1) => 0 (funcall f2) => 0 (funcall f2) => 1 (funcall f1) => 1 Vi har två generatorer (funktioner) med sina egna lokala variabeler tillstånd. Global variabel kan ju ej användas. Då kan bara en generator skapas.

23 Objektorienterad programmering. Idé: Fokusera dataobjektet. Objektet har en datatyp. Datatyperna ingår i en hierarki av typer. Associera värden (tillstånd) med objektet och funktioner (metoder) med objektet/typerna. Man skickar meddelanden till objekt. skriv ut dig addera 10 till dig hur gammal är du? Objektorienterad packetering: I Lisp kan vi representera dessa objekt med lexical closures. Vad vi får med den objektorienterade packeteringen är: 1) Interna tillstånden, data och metoder blir gömda. Kan endast nå via meddelanden till objektet. (information hiding) 2) Enda sättet att komma åt innehållet är vi meddelanden.

24 Exempel. Bankkonton Varje bankkonto har med sig associerat följande tillstånd: - kontoställningen - en funktion som beräknar räntan (på just detta konto) Ett bankkonto kan ta emot följande meddelanden: - sätt in x kr - ta ut x kr - skriv ut kontoställningen - vad är räntan (på årsbasis)

25 (defun skapa-bankkonto (&optional (konto 0) (ränte-fn # standard-ränte-fn)) (labels ((bankkonto (meddelande &optional argument) (cond ((eq meddelande in) (setq konto (+ konto argument)) ok) ((eq meddelande ut) (cond ((< konto argument) konto-för-litet) (t (setq konto (- konto argument)) ok))) ((eq meddelande ränta) (funcall ränte-fn konto)) ((eq meddelande konto) konto) (t (error "Fel meddelande: ~s" meddelande))))) # bankkonto)) Funktionen returnerar bankkonto i en omgivning där bankkonto, konto och ränte-fn har lokala värden. Denna funktion tar emot ett meddelande. Brukar kallas dispatch-funktion. (setq mitt-konto (skapa-bankkonto 0 # (lambda (konto) (* 0.08 konto)))) Värdet av mitt-konto är en lexical closure bankkonto konto - 0 ränte-fn

26 (funcall mitt-konto in 100) ; sätt in 100:- => ok (funcall mitt-konto konto) ; vad finns på kontot? => 100 (funcall mitt-konto in 200) ; sätt in 200:- => ok (funcall mitt-konto ut 50) ; ta ut 50:- => ok (funcall mitt-konto ut 300) ; försök ta ut 300:- => kontot-för-litet (funcall mitt-konto konto) ; vad finns på konto? => 250 (funcall mitt-konto ränta) ; räntan? => 20 (setq nytt-konto ; skapa ett nytt konto med (skapa-bankkonto ; 200:- och 10% ränta 200 # (lambda (konto) (* 0.10 konto)))) (funcall nytt-konto ut 125) => ok (funcall nytt-konto in 250) => ok (funcall nytt-konto konto) ; ta ut 125:- på nya kontot ; sätt in 250:- på gamla kontot ; kontoställningen på nya? Man skulle kunna definiera funktioner för respektive metod: (defun ta-ut (konto belopp) (funcall konto ut belopp)) (ta-ut nytt-konto 200) ; nytt-konto är en lexical closure

27 Nu kan vi förklara skillnaden med att använda quote eller function för lambda-uttryck. Med quote: (defun f (x) (quote (lambda (y) (+ x y)))) (funcall (f 1) 5) Error: Attempt to take the value of the unbound variable X. Formella parametern x är känt vid skapartillfället men ej vid exekveringstillfället. (setq x 10) (funcall (f 1) 5) => 15 Här är däremot den globala variabeln x känd. Med function: (defun g (x) (function (lambda (y) (+ x y))))) (funcall (g 1) 5) => 6 Formella parametern x är känt vid skapartillfället och sparas till exekveringstillfället.