Técnicas de programação funcional

Post on 26-May-2015

219 views 3 download

Transcript of Técnicas de programação funcional

Técnicas de Programação

Funcional

Em F# e Scala

Vinícius Hana e Juliano Alves

@vinicius_hana e @vonjuliano

Apresentação

Primeiro de tudo: não são paradigmas excludentes!

Programação funcional considera que todas as operações são funções

Todas as operações são funções

def f(x: Int, g: (Int) => Int) = g(x) + 3def g(x: Int) = x * 2

val resultado = f(4, g) // isso dá 11

5

Isso tem nome: funções de alta ordem

Perceberam que se parece com matemática?

Todas as operações são funções

f(x) = x + 3

g(x) = x * 2

(f o g) = f(g(x)) = g(x) + 3

g(4) = 4 * 2 = 8 f(g(4)) = 8 +3 = 11

8

Funções de alta ordem permitem algumas coisas bem legais!

Funções de alta ordem

let funcao = let lista = [0;1;2;3;4]List.map (fun x -> x * 2) lista

10

Agora, uma outra ideia:Dado f(x) = x + 1, se eu passar sempre 1, sempre vai dar 2?

Sim!E isso tem nome: transparência referencial

Dada a mesma entrada, obteremos sempre a mesma saídaOu seja, ausência de efeitos colaterais

Dá pra fazer isso em programação?Sim, usando imutabilidade!

Mutabilidade

public int Resultado { get; set; }

public void Dobrar(int numero){

Resultado *= 2;}

15

Imutabilidade

DateTime.Now.AddDays(1);// retorna novo datetime com a adição feita

16

Dada a mesma entrada, obteremos sempre a mesma saída

Ou seja, ausência de efeitos colaterais – mais confiabilidade no código

F# e Scala suportam mutabilidade e imutabilidade

Imutabilidade em Scala e F#

let x = 1 // imutavellet mutable x = 1 // mutavel

val x = 1 // imutavelvar y = 1 // mutavel

20

Isso ajuda demais em concorrência

Certo, mas como eu manipulo e altero os itens de uma lista, então? Ela não é imutável?

Simples: gere outra com nossa velha amiga recursão!

Com recursão, podemos compor e decompor listas

Recursão em listaslet rec reverse lista =

match lista with| head :: tail -> (reverse tail) @ [head]| [] -> []

def reverse[T](list: List[T]): List[T] = list match {  case head :: tail => reverse(tail) ++ List(head)  case Nil => Nil}

Percebeu uma estrutura diferente para compor a lista?

Essa estrutura se chama pattern matching

Ela lembra switch-case, porém com muito mais funcionalidade

Pattern matching

match coisa with| 1 | 3 -> …| head :: tail -> …| [] -> …| _ -> …

lista match {case 1 => …case head :: tail => …case Nil => …case _ => …

29

E se eu iterar em uma lista gigantesca, ou mesmo infinita?

Lista infinita? Isso não arrebentaria a memória?

Não se você tiver lazy evaluation!

Lazy evaluation

let x = 10let resultado = lazy (x + 10)

val x = { println("x"); 1 }lazy val y = { println("y"); 2 }

33

Vamos juntar tudo isso em uma implementação de Fibonacci?

Fibonacci

let rec fib n = match n with

| x when n > 2 -> 1| _ -> fib (n - 1) + fib (n - 2)

val seq: Stream[BigInt] = 0 #:: 1 #:: (seq zip seq.tail).map { case (a, b) => a + b }

def elemento(posicao: Int): BigInt = seq(posicao - 1)

35

Referências

Obrigado!

Vinícius Hana e Juliano Alves

@vinicius_hana e @vonjuliano

www.lambda3.com.br