programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav...

34
λ Uvod u funkcijsko programiranje Dinko Srkoč, Helix d.o.o.

Transcript of programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav...

Page 1: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

λUvod u funkcijsko programiranje

Dinko Srkoč, Helix d.o.o.

Page 2: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Lambda

Haskell

Clojure

Racket

Philip WadlerFaith, Evolution, and Programming LanguagesQCon 2012

Abelson, SussmanSICP, 2. izdanjeThe MIT Press

Izvori:http://mitpress.mit.edu/sicp/full-text/book/book.htmlhttp://www.infoq.com/presentations/Faith-Evolution-Programming-Languages

Page 3: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

λ - počeci računarstva

Page 4: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Povijest

● 1936 - netipizirani λ račun

● 1940 - tipizirani λ račun

Alonzo Church (1903 - 1995)Izvor: http://en.wikipedia.org/wiki/File:Alonzo_Church.jpg

Page 5: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Povijest - λ-računformalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije

λ-račun je ekvivalentan univerzalnom Turingovom stroju

funkcijski jezici kao razrada λ-računa Alonzo Church (1903 - 1995)

Page 6: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Povijest - λ-račun

λx.t ↔ f(x) = t

Alonzo Church (1903 - 1995)

Page 7: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Imperativno programiranje

Niz naredbi (eng. statement) koje mijenjaju stanje programa.

● mijenjanje vrijednosti varijabli● korištenje pridruživanja● kontrolne strukture - if-then-else, petlje,

break, continue, ...

Page 8: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Što je funkcijsko programiranje?

● u ograničenom smislu:programiranje bez promjenjivih varijabli, pridruživanja, petlji, ...

● u proširenom smislu:programiranje koristeći funkcije

Martin Odersky, Functional Programming Principles in Scala, Coursera.org

Page 9: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Što je funkcijski programski jezik?

● u ograničenom smislu:programski jezik koji ne podržava promjenu vrijednosti varijabli, pridruživanja ili imperativne kontrolne strukture

● u proširenom smislu:programski jezik koji olakšava rad s funkcijama

Martin Odersky, Functional Programming Principles in Scala, Coursera.org

Page 10: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Funkcijski programski jezici

● Haskell● Standard ML, Ocaml, F#● Lisp, Scheme, Racket, Clojure*● Scala*● Groovy*, Ruby, Smalltalk, JavaScript

(*) jezici rađeni za JVM

Page 11: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Usporedba:funkcijski ↔ imperativno

funkcijsko programiranje

opisuje računanje kao evaluaciju matematičkih funkcija

što treba napraviti

imperativno programiranje

opisuje računanje kao niz naredbi koje mijenjaju stanje programa

kako treba nešto napraviti

Page 12: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjeri

Talk is cheap. Show me the code.

Linus Torvalds

Izvor: http://en.wikipedia.org/wiki/File:Linus_Torvalds.jpeg

Page 13: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 1

Funkcija za računanje faktorijela

n! = n * (n - 1) * (n - 2) * ... * 1

Page 14: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 1

Funkcija za računanje faktorijela

// n! = n * (n - 1) * ... * 1public long factorial(long n) { long res = 1; for (long i = n; i > 0; i--) { res = res * i; } return res;}

Java

Page 15: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 1 - rekurzija

Funkcija za računanje faktorijela

// n! = n * (n - 1) * ... * 1public long factorialR(long n) { if (n == 1) return 1; else return n * factorialR(n - 1);}

Java

Page 16: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 1 - rekurzija

Funkcija za računanje faktorijela

// n! = n * (n - 1) * ... * 1public long factorialR(long n) { if (n == 1) return 1; else return n * factorialR(n - 1);}

Java

● algoritam bliži matematičkom izrazu

● nema pridruživanja, promjenjivih vrijednosti

● java.lang.StackOverflowError

Page 17: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 1 - rekurzija

Funkcija za računanje faktorijela

// n! = n * (n - 1) * ... * 1def factorial(n: Long): Long = if (n == 1) 1 else n * factorial(n - 1)

Scala

još uvijekjava.lang.StackOverflowError!

Page 18: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 1 - rekurzija

Funkcija za računanje faktorijela

// n! = n * (n - 1) * ... * 1def factorial(n: Long): Long = { @scala.annotation.tailrec def iter(n: Long, acc: Long):Long= if (n == 1) acc else iter(n - 1, n * acc)

iter(n, 1)}

Scala

Tail Call Optimization

Page 19: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Rekurzija

Recursion is the root of computation since it trades description for time

Alan J. Perlis (1922 - 1990)

To iterate is human, to recurse divine

L Peter Deutsch (1946)

Izvori:http://amturing.acm.org/photo/perlis_0132439.cfmhttp://www.vintage.org/2003/main/bio.php?id=54&back=37

Page 20: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 2

Broj slova u popisu imena

public List<Integer> lengths(List<String> names) { List<Integer> res = new ArrayList<>(); for (String name : names) { res.add(name.length()); } return res;}

Java

Page 21: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 2

Broj slova u popisu imena

def lengths(names: List[String]): List[Int] = if (names.isEmpty) List() else names.head.length :: lengths(names.tail)

Scala

Page 22: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 2

Broj slova u popisu imena

def lengths(names) { names.collect { name -> name.size() }}

Groovy

Page 23: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 2 - funkcije

Broj slova u popisu imenaGroovy

def lengths = { name -> name.size()}

names.collect(lengths)

Groovy

● funkcija kao građanin prvog reda

● funkcije višeg reda

Page 24: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Primjer 2 - funkcije

Groovy

def upper = { name -> name.toUpperCase()}

names.collect(upper)

Groovy

● funkcija kao građanin prvog reda

● funkcije višeg reda

Page 25: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Funkcije višega reda

// map, collect, selectdef map[A, B](xs: List[A], f: A ⇒ B): List[B]

// filter, findAll, wheredef filter[A](xs: List[A], f: A ⇒ Boolean): List[A]

// foldLeft, reduce, injectdef foldLeft[A, B](xs: List[A], z: B, f: (B,A) ⇒ B): B

Scala

Page 26: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Funkcije višega reda

// map, collect, selectList(1, 2, 3) map { x ⇒ x * x } // ... List(1, 4, 9)

// filter, findAll, where1 to 10 filter (_ % 2 == 0) // ... Vector(2, 4, 6, 8, 10)

// foldLeft, reduce, injectList(1, 2, 3).foldLeft(0) { (acc, x) ⇒ acc + x } // ... 6

Scala

Primjeri

Page 27: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Closure

Groovy

def add(x) { { y -> x + y }}

def add5 = add(5) // { y -> x + y }

add5(10) // vraća 15

Groovy

Page 28: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Closure

Groovy

def add(x) { { y -> x + y }}

def add5 = add(5) // { y -> x + y }

add5(10) // vraća 15

Groovy

● x unutar leksičkog dosega● closure = funkcija + okolina

Page 29: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Kompozicija - f ∘ g(f ∘ g)(x) = f(g(x))

def longest = { strs -> strs.inject { max, s -> max.size() > s.size() ? max : s}}def capitals = { strs -> strs.findAll { it == it.capitalize() }}def strToList = { str -> str.tokenize() }

def longestCapital = longest << capitals << strToList

longestCapital 'Bratac Jaglenac i sestrica Rutvica'// vraća 'Jaglenac'

Groovy

Page 30: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Currying (Schönfinkeling)transformacija funkcije koja prima višestruke argumente u niz funkcija s jednim argumentom

// opsegTrokuta: (Int, Int, Int) ⇒ Intval opsegTrokuta=(a: Int, b: Int, c: Int) ⇒ a + b + c

// cOpseg: Int ⇒ (Int ⇒ (Int ⇒ Int))val cOpseg = opsegTrokuta.curried

val o1 = cOpseg(1) // o1: Int ⇒ (Int ⇒ Int)val o2 = o1(2) // o2: Int ⇒ Intval o3 = o2(3) // o3: Int, o3 == 6// opsegTrokuta(1, 2, 3)

Scala

Haskell Curry (1900 - 1982)Izvor: http://www.apprendre-math.info/history/photos/Curry.

jpeg

Page 31: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

The Good, the Bad and ...

● bez nuspojava - lakše razumjeti i predvidjeti ponašanje programa

● bez mutirajućih varijabli - lakši paralelni rad

● deklarativni kôd - često kraći i razumljiviji

● funkcijski jezici su često manje efikasni

● "drugačija" programska paradigma

● rekurzija i StackOverflowError

Page 32: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

PonovimoFunkcijsko programiranje:● bez promjenjivih varijabli● upotreba čistih funkcija

Značajke:● petlja → rekurzija● deklarativni stil● funkcije kao vrijednosti i funkcije višeg reda

Page 33: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Još malo citataThe way we can tell it's C# instead of Haskell is because it's nine lines instead of two.

Philip Wadler

A monad is a monoid in the category of endofunctors, what's the problem?

James Iry (kvazi-citirao Wadlera)

Remember, kids: if you program in a language with side effects, the terrorists win.

Tommah (Haskell Weekly News, 7.5.2007)

Page 34: programiranje Uvod u funkcijsko λ · PDF filePovijest - λ-račun formalni sustav za ispitivanje definicije i aplikacije funkcije te za definiranje izračunljive funkcije λ-račun

Pitanja

?Hvala na pažnji