Föreläsning 1 i Programmeringsparadigm Programmeringsparadigm : Vad menas med programmeringsparadigm? Webster s New World dictonary : paradigm n. [< Gr. para-, besides + deigma, example] 1. an example or modell I vetenskapasteori: Bakomliggande tankemodell för samhörande teorier. Ex i fysiken. I datalogi: Bakomliggande tankemodell för olika sätt att skriva och utforma dator-program. Olika programmeringsspråk kan grupperas i olika paradigmer. program, programme n. [< Gr. pro-, before + graphein, skriva] 1. A list of events, pieces, performers, etc, as of an entertainment 2. A plan of procedure v.t to schedule in a program I datalogi : föreskrift, en beskrivning av vad en dator skall göra. När använder man olika paradigm i datalogi? Programmeringspråk och kodning versus Design utfomning (Vattenfall, UML?) och paradigmer versus Algoritmer Datalogins paradigm? Hur många paradimer finns det? Vilka paradimer används? Varför kunna olika paradigm? Vetenskap och konst. TH förvalta och/eller förnya (varifrån?) tekniken? Ej helt oberoende. Kunskap i t ex Haskell leder till bättre Java-program. Perspektiv. Kanske paradigmskifte? Ex OO, kalkylblad, 5:e generationes datorer, DNA. Andra aspekter på programmeringsspråk: Hårt typade språk: I princip oberoende av paradigm. Hårt typade språk : Man "tvingas" tänka sig in i olika typer, kompilatorn hittar många fel. Otypade språk: Full frihet Pekare (referenser): Oberoende av paradigm? Osynligt? Halvautomatiskt (Java)? Explicit (Pascal, C)?
Vad är programmering? Tre aspekter ( inspirerat av Sten Henriksson, Lund): Programmering är en sorts matematik och logik. Acceptabla språk börjar väl med bättre funktionella språk? Körbara specifikation? Körbar Design? Bevis att programmen är korrekta. Passar bra med funktionella paradigmen och den logiska. Programmering är algoritmer. Vad är beräkningsbart? Går allt att göra? O(n). Turing maskiner mm. Programspråk (t o m paradigmer? ) sekundärt? Numerisk analys. Ganska paradimoberoende? Programmering är klassik ingenjörskonst. Nedbrytning av moduler. Gränsnitt, Design och implementation. Implementation, programspråk (t o m paradigmer? ) sekundärt? Programmering är bara en del av ett system. Design av systemet det viktiga. Design och implementation av programmet sekundärt. Att vara systemerare är "finare" (och mer välavlönat) än att vara programmerare. "ADB". Användargränssnittet, samverkan med hela systemet det viktiga. Översikt programmeringssparadigmer se nästa sida. Översikt paradigmhistoria, se några sidor framåt (endast i pappersupplagan). Denna kurs: Imperativa paradigmen Objektinriktade paradigmen Funktionella paradigmen Logik paradigmen : ~0.4 p C-programmering i lp 2. Java som imperativt språk. : Återblick på OO och Java : ~1.4 p Haskell : ~1.6 p Prolog samt Internetprogrammering : ~0.4 p i lp 2.
paradigm Imperativ ide och semantik Simulering av Von Neuman-dator CPU styrning ALU Beräkning (evaluering) av uttryck Primärminne Kod (funktioner, procedurer, subrutiner..) Variabler, aggregat av variabler lokala / statiska /på heapen Tilldelning := Flödeskontroll Sekvens ; Snurror Alternativ OO Imperativ med objekt och arv CPU styrning ALU Primärminne Beräkning (evaluering) av uttryck Variabler Objekt, aggregat med metoder Kod (funktioner, procedurer, subrutiner..) Tilldelning := Flödeskontroll Sekvens ; Snurror Alternativ Funktionell Logisk Händelsestyrd Jämnlöpande Matte (funktioner) som programmeringsspråk A -> B Beräkning (evaluering) av uttryck, ofta med funktioner Kod (def av funktioner och typer) Logik (predikat, funktioner -> Bool) som programmeringsspråk -> Bool Beräkning (evaluering) av predikat, ofta med förslag hur logiska varaibler skall instasieras Kod (def av predikat) Användarprocess som styr Programexekveringen ( lyssanre i java) Flera process eller trådar (Thread i Java) som styr varandra, synkronisering, moniorer mm
Kort (personlig) karaktärisik : Imperativ : Så har man alltid gjort och alla andra gör så här! Dessutom kan jag redan en del! "Sjävklart" att man instruerar datorn i vilken ordning saker skall göras. Programmering som simulering. I verkliga livet går tiden, i datorn programmet. Avspeglar datorns konstruktion. OO (objektorienterad, objekt inriktad) : Simuleringsynen ännu mer betonad. Utveckling av imperativa pardigmen, men delvis inkompatibelt. Nära hur "vanliga" männsikor ser på värden, värden består av objekt av olika sorter (klasser) med både egenskaper (attribut) och handlingsmönster (metoder). Funktionell: Ung = matte; Varför lära sig programmera när man redan kan matte/funktioner? Matematik har mångahundraåriga traditioner. Välgjorda språk, generella och ortogonala konsrtuktioner, "Hög nivå", korta "program" inga sidoeffekter. dvs svaret på frågan får man? / kan man? är i regel JA! Men går det inte lite väl sakta? Används det? Man börjar på detta sätt i Göteborg, Luleå, Umeå, Linköping, KTH före ca 1995, SU (mat-datalogisk), Oxford, m fl ställen Logik: Ung =logik; Varför lära sig programmera när man redan kan logik/relationer? Logik har hundraåriga traditioner, "hög nivå" Ren logik programmering / i praktiken kompromisser. "Hög nivå", mycket korta "program" Men fattar man vad som händer igentligen? Men går det inte lite väl sakta? Prolog populärt i AI (artificiell intellegens). Händelsestyrd: Många (de flesta)program skall ju göra nåt annat än bara "räkna ut nåt", dvs samverka med verkligheten. Egen paradigm? Grafiska användargränssnitt (GUIi). Jämlöpande : "Naturligt" att saker och ting kan ske parallellt. CPU : kostar ju inget, varför inte använda hundratals, så man slipper vänta? Egen paradigm? Samma sak som händelsestyrd? Synkronisering och utbyte av data, hur? "Ju flera kockar ju sämre soppa"?
Ett tentamensproblem löst i imperativ Java, OOJava, funktionella språket Haskell och logikspråket Prolog: En kurs har två moment, tentamen på vilket ges betyg 0.. 5, och laborationer med tre laborationer vilka kan ges betyget G eller _. Slutbetyg ges till de personer som har G på alla tre labbarna och minst betyg 3 på tentan. Slutbetyget blir då lika med tentabetyget. Skriv ett program som ger som resultat en betygslista med betyg för de personer som är godkända. Imperativ Java: Kort version: Indata en sträng "<namn>,<betyg tenta>.>g/_ för varje godkänd labb>" Utdata : Trycks på std.out Exempel på körning:..>java SlutbetygShort "Per,5.G_G" "Siv,5.GGG" "Eva,3.GGG" Siv 5 Eva 3 */ public class SlutbetygShort { // Java as an imperative language, main static, no objekts public static void main (String [] arg) { for (int i = 0; i < arg.length; i = i+1 ) { String name = (arg[i]).substring(0,(arg[i]).indexof(, )); int egrad = Integer.parseInt( (arg[i]).substring((arg[i]).indexof(, )+1, (arg[i]).indexof(. ))); String labs = (arg[i]).substring((arg[i]).indexof(. )+1); if ( (labs.equals("ggg")) && (egrad >= 3)) { System.out.println(name + " " + egrad); Primärminne i name egrad labs public static main lokala variabler på "stacken" allokerade när main kör variabler på "heapen" allokerade när main kör med new
Version med poster = "records " = "structures" = klasser utan instansvariabler. Java som imperativt språk i ett något större program: Exempel på körning:..>java Slutbetyg "Per,5.G_G" "Siv,5.GGG" "Eva,3.GGG" Siv 5 Eva 3 */ class Student { // "imperative record/structure" NB. no methods!! String name ; int egrad; // grade on examination String labs;// G is passed laboration, examples GGG, G_G class Grade { // "imperative record/structure" NB. no methods!! String name; int grade; public class Slutbetyg { // Java as an imperative language // all methods static, no instance methods // But; // Java arrays and strings has been used for convenience; // arrays and string in Java must be treated as objects // In Pascal and other imperative languages you donot have to do // lines marked by // not in Pascal // also standard methods for strings have been used for convenience; // in an imperative language // (arg[i]).indexof(, ) would have looked as indexof(arg[i],, ) // static Student [] student; static Grade [] grade; public static void main (String [] arg) { student = new Student [arg.length]; // not in Pascal grade = new Grade [arg.length]; // not in Pascal // More functional style : makestudents(arg, student); // student = students(arg); makegrades(student, grade); // grade = grade(student); printgrades(grade); static void makestudents(string [] arg, Student [] st) { for (int i = 0; i < arg.length; i = i+1 ) { st[i] = new Student(); // not in Pascal (st[i]).name = (arg[i]).substring(0,(arg[i]).indexof(, )); (st[i]).egrad = Integer.parseInt( (arg[i]).substring((arg[i]).indexof(, )+1, (arg[i]).indexof(. ))); (st[i]).labs = (arg[i]).substring((arg[i]).indexof(. )+1);
static void makegrades(student [] st, Grade [] gr) { for (int i = 0; i < st.length; i = i+1 ) { gr[i] = new Grade(); // not in Pascal gr[i].name = new String (st[i].name); // newstring not in Pascal if ( (((st[i]).labs).equals("ggg")) && ((st[i]).egrad >= 3)) { gr[i].grade = st[i].egrad; else { gr[i].grade = -1; static void printgrades(grade [] gr) { for (int i = 0; i < gr.length; i = i+1 ) { if ((gr[i]).grade > 2) { System.out.println((gr[i]).name + " " + (gr[i]).grade); class Student { // "imperative record/structure" NB. no methods!! String name ; int egrad; // grade on examination String labs;// G is passed laboration, examples GGG, G_G class Grade { // "imperative record/structure" NB. no methods!! String name; int grade; Primärminne stacken statiska heapen koden variabler student grad name egrad labs name grade...... main makestudent makegrades printgrades "metoder" dvs procedurer, alla static void lokala variabler, som finns när en viss procedur kör statiska variabler student grade med refererade variabler som skapas med new under körningen
Objektorienterad Java: Exempel på körning:...>java SlutbetygOO "Per,5.G_G" "Siv,5.GGG" "Eva,3.GGG" Siv 5 Eva 3 public class SlutbetygOO { // Java as an OO language // Objects of type Student has instance methods. static Student [] student; public static void main (String [] arg) { student = new Student [arg.length]; for (int i = 0; i < arg.length; i = i+1 ) { student[i] = new Student(arg[i]); if (student[i].ispassed()) { System.out.println(student[i].getName() + " " + student[i].getfinalgrade()); class Student { String name ; int egrad; // grade on examination String labs;// G is passed laboration, examples GGG, G_G boolean passed; // passed course public Student(String input) { name = input.substring(0,(input).indexof(, )); egrad = Integer.parseInt( input.substring(input.indexof(, )+1, input.indexof(. ))); labs =input.substring(input.indexof(. )+1); passed = (labs.equals("ggg")) && (egrad >= 3); public String getname() { return name; public int getfinalgrade() { if (passed) { return egrad; else { return -1; public boolean ispassed() { return passed;
Primärminne stacken statiska heapen statisk variabler kod student name egrad labs passed Student getname getfinalgrade ispassed...... main "metod" procedurer, static void lokala variabler, som finns när en viss procedur kör statiska variabler student grade med refererade variabler som skapas med new under körningen VARJE Student-objekt innehåller nu både "data" och (begräppsmässigt) metoder (kod) Varför är OO ett framsteg jämfört med traditionell imperatov programmering? Jo, antag att programmet skall genarilseras för flera olika sorters studenter, t ex teknologer som skall ha betyg 3 4 5 och universitetsstudenter med betyg G VG och.. I den traditonella imperativa lösningen måste vi då på en massa ställen stoppa in if- eller case-satser eftersom metoderna skall fungera olika, olika sorters variabler skall finnas osv: if student == Teknolog... else if student == Universitetsstudent.. else if... Detta är jobbigt och svårt och måste i större program göras på en massa ställen varje gång vi hittar på en ny sorts studenter. Med OO skriver vi en Student-super-klass som innehåller det som är gemensamt för alla sorters studenter, döper vi om vår gamla Student klass till Teknolog (som ärver nya Student) och en ny klass Universitetsstudent (som ärver nya Student) osv. De gamla programmet behöver inte ändras alls! För varje ny studentsort behöver vi bara skriva en ny klass, som innehåller allt nytt på ett och samma ställe. Mycket bekvämt. Detta är finnesen med arv och dynamisk bindning, dvs att alla gör en viss metod "på sitt sätt".
Tre Haskell-lösningar: Skriv ett program slutbetyg :: [(String, Int,[Char])] -> [(String, Int)] som givet en lista av typ [(String, Int,[Char])] med personers namn, tentamensbetyg och labresultat retunerar slutbetyg för de personer som skall ha godkänt på kursen. Exempel : res = [("Per", 5, [ G, _, G ]), ("Siv", 5, [ G, G, G ]), ("Eva", 3, [ G, G, G ])]...> slutbetyg res [("Siv",5),("Eva",3)] Version a : Skriv programmet utan att använda några högre ordningens funktioner eller listomfattning. slutbetyg [] = [] slutbetyg ((namn, tenta, lablista):ntls) lablista == [ G, G, G ] && tenta >= 3 = (namn, tenta) : slutbetyg ntls otherwise = slutbetyg ntls Version b : Version c : Skriv programmet med map och filter slutbetyg lista = map f (filter p lista) where f (namn, tenta, _ ) = (namn, tenta) p (_, tenta, lablista) = lablista == [ G, G, G ] && tenta >= 3 Skriv programmet med listomfattning slutbetyg lista = [ (namn,tenta) (namn,tenta,[ G, G, G ])<- lista, tenta>=3] En Prolog -lösning : Exempel på körning : slutbetyg([r(per,5,[g,n,g]),r(siv,5,[g,g,g]),r(eva,3,[g,g,g])], Slubs). Slubs = [slutbetyg(siv,5),slutbetyg(eva,3)]? ; no. slutbetyg([], []). slutbetyg([r(namn, Tenta, [g, g, g]) Ntls ], [slutbetyg(namn, Tenta) Ntls1]) :- Tenta >=3, slutbetyg( Ntls, Ntls1). slutbetyg([r(_, _, Lablista) Ntls ], Ntls1) :- % Om man inte testar member(n, Lablista), % för underkänt får man slutbetyg( Ntls, Ntls1). % ytterligare felaktiga svar % vid backtracking -1 poäng slutbetyg([r(_, Tenta, _) Ntls ], Ntls1) :- % Ingen rekursion för underkända Tenta <3, % - 5 päng slutbetyg( Ntls, Ntls1).