Scala Funktion und Closures – Handout Methoden 27.04.2010 – Schubert, Seilbeck Verkürzte FCF Syntax Der Datentyp kann weggelassen werden wo er für den Compiler ersichtlich ist. Das ist der Fall wenn eine FCF direkt an eine Methode übergeben wird, def name (param1: Typ,param2:Typ) welche den Datentyp vorgibt. :Typ={ } list.foreach((x:Int)=> println(x*x)) Überladung möglich. Sichtbarkeit ist list.foreach((x) => println(x*x)) standardmäßig public. In diesem Fall können auch die Klammern bei der Parameterdefinition weggelassen werden. Funktionsweise wie in Java: Lokale Funktionen Eine lokale Funktion ist eine Funktion in einer Funktion. Die innere Funktion kann nur aus der äußeren Funktion aufgerufen werden. Die innere Funktion hat lesenden und schreibenden Zugriff auf die Variablen der äußeren Funktion und auf die Membervariablen. First Class Functions Funktionen können in Variablen gespeichert werden. var sqr = (x:Int) => x * x Die Funktion in der Variable kann folgendermaßen aufgerufen werden: sqr(2) //= 4 Mehrere Parameter werden durch Kommas getrennt. list.foreach(x => println(x*x)) Platzhalter Syntax Der „_“ kann als Platzhalter für einen Parameter verwendet werden. Var b = x => println(x) var b = println(_:Int) Möglich ist auch die Verwendung von mehreren Parametern. Auch hier gilt, dass der Datentyp weggelassen werden kann, wo er für den Compiler ersichtlich ist. list.foreach(println(_)) Ein Nachteil der Platzhaltersyntax ist dass der Parameter jeweils nur einmal verwendet werden kann. var sum = (x:Int,y:Int) => x + y Partielle Funktionen Die Variable kann neu zugewiesen werden wobei Der „_“ kann auch ganze Parameterlisten ersetzen. die Signatur (inkl. Rückgabewert) beibehalten werden muss. var minus=(_:Int) - (_:Int) Bei mehrzeiligen Ausdrücken muss der var b = minus(_:Int,_:Int) Methodenrumpf in {} geklammert werden. var c = minus _ b(5,3) SqrPlus2 = (x:Int) =>{ var a= x*x; a+2; Bei der Anwendung auf eine überladene Funktion } meldet der Compiler einen Fehler. Ein Teil der Parameter eines Funktionsaufrufes können mit Werten vorbelegt werden. Scala Funktion und Closures – Handout var minus=(_:Int) - (_:Int) b=minus(5,Int:_) b(3) //=2 b=minus(Int:_,3) b(5) //=2 Falls die ganze Parameterliste übernommen werden soll und der Compiler eine Funktion erwartet, kann der „_“ komplett weggelassen werden. list.foreach(println _) list.foreach(println) 27.04.2010 – Schubert, Seilbeck } Varargs Funtkionsweise der Varargs in Scala ist fast identisch mit denen in Java. def sum(args :Int*)={ var sum=0 for(arg <- args){sum += arg} return arg } Statt „...“ wird in Scala ein * verwendet, um ein Vararg zu kennzeichnen. Im Gegensatz zu Java ist es nicht möglich, direkt Closures ein Array an ein Vararg zu übergeben. Stattdessen FCF haben Zugriff auf alle Variablen, die sich im muss an den Array „:_*“ angehängt werden. „:_*“ Scope befinden. Greift nun eine FCF auf eine bringt den Compiler dazu, jedes Element eines Variable zu, welche nicht als Parameter definiert Arrays in einen einzelnen Parameter ist, wird sie als Closure bezeichnet. umzuwandeln. def createClosure ():(Int)=>Int={ sum(array:_*) var noParameter = 3 (x: Int)=> x + noParameter } Endrekursionen var closure = createClosure() Compiler muss Endrekursionen (tail recursions) closure(8) // = 11 wegoptimieren • Rekursiver Aufruf muss am Ende der Kontext des Closures bleibt bis zum letzten Aufruf Funktion stehen bestehen. Bei der Ausführung eines Closures ist der aktuelle • Laufzeit nahezu identisch wie iterative Zustand der Variablen maßgeblich. Lösung def createClosure ():(Int)=>Int={ var noParameter = 3 var closure = (x: Int)=> x + noParameter noParameter = 5 closure(8) // = 13 } Ein Closure kann äußere Variablen verändern def createClosure ()={ var noParameter = 3 var closure =(x:Int)=> x + (--noParameter) closure(8) println(noParameter) //2 Optimierung kann mit dem Compilerparameter g:notailcalls ausgeschaltet werden Funktionale Programmierung Orientiert sich an den Funktionen aus der Mathematik. y=sin(x) Mathematische Funktionen sind frei von Seiteneffekten. Das Ergebnis hängt allein vom Parameter ab. Der Kontext spielt keine Rolle. Solche Funktionen sind gut verständlich und leicht testbar. Scala Funktion und Closures – Handout Durch den Einsatz von unveränderlichen Variablen wird ein Teil dieses Verhaltens in einer Programmiersprache nachgebildet. Dadurch ergeben sich folgende Vorteile: • • • Nahezu alle Probleme bei Multithreading werden vermieden Verringert Komplexität Daten müssen nicht gekapselt werden Allerdings muss man auch in Kauf nehmen das viele Objekte erzeugt werden müssen und sich manche Bereiche nur schwer bis gar nicht funktional lösen lassen z.B. IO. Scala ist eine Multiparadigmen Sprache (funktional und objektorientiert). Daher bietet Scala für funktionale Programmierung folgende Unterstützung: • Vals statt vars • Funktionale Datentypen (z.B. List ist immutable) • Operationen auf Collections die ohne vars auskommen (z.B. foreach) • Actors 27.04.2010 – Schubert, Seilbeck