Funktionales Programmieren in CindyScript Alles ist eine Funktion! Primitive Datentypen ● Datentyp <number>: komplexe Zahlen 3+4*sin(5)*sqrt(-1) ● Datentyp <string>: Zeichenketten "hallo "+"welt" ● Datentyp <boolean>: true oder false length("a")==0 & 4~<=3 Funktionsdefinition g(x) := x^2 f(x, y) := length(x)+y h(x) := "x ist "+x Als nächstes: Rekursion fac(n) := n*fac(n-1) ??? Wir brauchen eine Abbruchbedingung Bedingungen Überraschung: Auch „if“ ist eine Funktion if(bed, expr1, expr2) Falls bed=true expr1, sonst expr2 ● Damit Fakultät wie folgt: fac(n) := if(n>1, n*fac(n-1), 1) Sequenzen und Seiteneffekte Mit dem bisherigen Konzept keine Interaktion mit der „Zeichnung“ möglich ● Globale Variablen ● Zuweisungsoperator „=“ ● Neuer Datentyp <geo> (z.B Punkte, Geraden...) ● Zugriff auf Eigenschaften von <geo> mit „.“ ● ● Es wird auch der leere Wertebereich zugelassen „___“ Sequenzialisierungsoperator „;“ Nacheinanderausführung Definiton von „;“: (expr1; expr2) -> ret wobei expr1 und expr2 nacheinander auszuwertende Ausrücke, ret der Rückgabewert von expr2 ● „;“ ist assoziativ ((a;b);c)=(a;(b;c)) ● also Klammern meist optional Beispiele g(n) := (A.x = n; sin(n)) f(i) := println(i); f(“hallo“) i = 1; while(i < 10, println(i); i = i+1 ) ● ● Vorteil: Imperative Programmierung möglich Nachteil: Funktionsdefinition wird sequentiell Listen ● Datentyp <list> [true, "servus", A, [2, 3]] ● Mengen (auch Listen) set([2,2,3]) -> [2,3] ● Vektoren (auch Listen) ● Matrizen (Listen von Listen) [[1, -1], [-1, 1]] Listen/Mengenoperationen ● ++, --, ~~, reverse, sort, set ● sum, max, min ● _, length, contains ● .. sort([ [], "f", true] ++ 1..3) -> [true, 1, 2, 3, "f", []] (2..8)_5 -> 6 Vektor/Matrixoperationen ● +, * (so polymorph wie möglich) ● transpose, inverse, eigenvectors, linearsolve ● isnumbervector, ismatrix ● det, ||, |,| x = [1,2,3]; x = x/|x|; x*x -> 1 Funktionen als Argumente ● ● Wie plotten wir eine Funktion? Der Plot-Befehl muss eine Funktion übergeben bekommen ● In CindyScript: nur bei Bibliotheksfunktionen ● Spezielle „Laufvariable“ # Beispiele ● Plot: plot(f(#)) ● Listentraversierung: list = 1..100; forall(list, if(even(#), println(#))); oddnumbers = select(list, odd(#)); sum(list, #^2); Erste Programmierbeispiele ● Euklidischer Algorithmus (iterativ) : euklid1(a,b) := ( while(b != 0, h = mod(a,b); a = b; b = h; ) a ) ● Euklidischer Algorithmus (rekursiv) : euklid2(a,b) := if(b==0, a, euklid2(b, mod(a,b))); Rechnen mit Polynomen ● Berechnung des Funktionswertes: poly(koef, x) := sum(1..length(koef),koef_# * x^(#-1)); ● Differenzieren / Stammfunktion bilden: diff(koef) := apply(2..length(koef), (#-1)*koef_#); stamm(koef, c) := c++apply(1..length(koef),koef_#/#); Berechnung von Primzahlen ● Das Sieb des Eratosthenes : sieb(liste) := ( laenge = length(liste); if(laenge > 0 , liste_1 <: sieb(liste -(1..(liste_laenge))*liste_1) ,liste) ); sieb(2..100); Berechnung von Primzahlen ● Einfacher in CindyScript : divisors(x) := select(1..x,mod(x, #) == 0); primes(n) := select(1..n, length(divisors(#)) == 2); primes(100); Schwarmsimulation ● Code (1): punkte=[P1,P2,P3,P4,P5,P6,P7,P8, P9,P10,P11,P12,P13,P14,P15,P16]; n=round(|G1,G2|/|G2,G3|*6); forall(punkte,p, sortiert= sort(punkte,abs(p.xy-#.xy)); mitte= sum(2..(n+1),(sortiert_#).xy)/n; Schwarmsimulation ● Code (2): vdir=(mitte-p.xy); v=p.v+vdir; p.color=hue(abs(v)/6); if(abs(v)>3,v=3*v/abs(v)); p.v=v; ); Darstellung von Lindenmeyer- oder L-Systeme ● ● Grundlage einer axiomatischen Theorie biologischer Entwicklung. finden Anwendung in der Computergraphik: – Erzeugung von Fraktalen – Modellierung von Pflanzen. Darstellung von Lindenmeyer- oder L-Systemen ● ● wesentliche Prinzip: sukzessive Ersetzung von Einzelteilen eines einfachen Objektes mittels sogenannter Produktionsregeln. Diese Ersetzungen können rekursiv durchgeführt werden Darstellung von Lindenmeyer- oder L-Systeme ● Code (1) : turtle(x):=( (if(x=="F",foreward)); (if(x=="+",left)); (if(x=="-",right)); (if(x=="[",open)); (if(x=="]",close)); (if(x=="A",ball1)); (if(x=="B",ball2)); ) Darstellung von Lindenmeyer- oder L-Systeme ● Code (2) : list(x):=( gsave(); translate((G.y,-G.x)); repeat(length(x),turtle(x_#)); grestore(); ); repeat(n,s=replace(s,"F",Fcode.val)); list(s);