Introdução à Programação Funcional com Elixir

Introdução à Programação Funcional com Elixir

Slides da talk do CaquiCoders realizado no dia 9 de novembro de 2018: https://www.meetup.com/pt-BR/CaquiCoders/events/263335398/

712a8a8a2ac5145874ab33c328a17f05?s=128

Lucas Santos

February 21, 2019
Tweet

Transcript

  1. 3.
  2. 5.
  3. 6.
  4. 9.

    "Orientação a Objetos é um paradigma da programação baseada no

    conceito de 'objetos', que podem conter dados na forma de campos (conhecidos como atributos) e códigos, na forma de procedimentos (também conhecidos como métodos)"
  5. 11.

    class Dog attr_accessor :name, :favorite_toy def initialize(name, favorite_toy) @name =

    name @favorite_toy = favorite_toy end def change_favorite_toy(toy) @favorite_toy = toy end end
  6. 16.

    Obtenha o primeiro contato da agenda do usuário. Verifique se

    o nome desse usuário se inicia com a letra "A". Se iniciar com a letra "A", exiba seu email. Caso haja contatos na agenda, vá para o próximo. Exemplo do livro Programação Funcional em .NET, de Gabriel Schade. Publicado pela Editora Casa do Código em 2017 Linguagem imperativa
  7. 17.

    A programação imperativa foca no como uma tarefa deve ser

    realizada, especificando o passo-a-passo.
  8. 18.

    Prós: • permite ter controle sobre a eficiência • consolidado

    e de dominância no mercado. Contras: • difícil legibilidade • foca na descrição passo-a-passo do algoritmo.
  9. 19.

    Exiba o email de todos os contatos da sua agenda

    que o nome inicie com a letra "A". Exemplo do livro Programação Funcional em .NET, de Gabriel Schade. Publicado pela Editora Casa do Código em 2017 Linguagem declarativa
  10. 21.

    Prós: • leitura mais fácil • reduz efeitos colaterais •

    fácil testabilidade Contras: • não oferece declaração explícita de variáveis, que às vezes são necessárias
  11. 25.

    Uma função pura é uma função que dada as mesmas

    entradas, sempre será dada a mesma saída e não possuirá side-effects (efeitos colaterais).
  12. 27.

    def count(phrase) do phrase |> String.split( " ") |> Enum.reduce(%{},

    fn word, acc -> Map.update(acc, word, 1, fn x -> x + 1 end) end) end
  13. 28.

    def count(phrase) do Logger.info( "counting #{phrase}") phrase |> String.split( "

    ") |> Enum.reduce(%{}, fn word, acc -> Map.update(acc, word, 1, fn x -> x + 1 end) end) end Side-effect
  14. 35.

    Web application HTTP request HTTP response Exemplo da palestra de

    Scott Wlaschin: Functional programming design patterns (https://vimeo.com/113588389)
  15. 37.

    Imutabilidade é um conceito que define que dados não podem

    ter seus estados alterados depois de criados.
  16. 38.

    int s = 0; for (int index = 0; index

    < data.Length; index++){ s += data[index]; } Estado sendo alterado
  17. 39.

    list = [1,2,3,4,5] new_list = Enum.map(list, fn item -> item

    * 2 end) IO.inspect(list) # => [1, 2, 3, 4, 5] IO.inspect(new_list) # => [2, 4, 6, 8, 10] Estado não é alterado
  18. 41.

    Elixir é uma linguagem de programação do paradigma funcional, concorrente

    e tolerante à falhas. Foi criada em 2012 por José Valim como um projeto de pesquisa e desenvolvimento da Plataformatec.
  19. 43.

    IEx - Elixir Interactive Shell. É a ferramenta que iremos

    usar para executar nossos exemplos. Ela pode ser chamada pelo terminal com o seguinte comando: iex
  20. 44.
  21. 45.

    Átomos Átomo é um tipo de dado cujo o valor

    é o seu nome. iex> :foo :foo iex> :foo == :bar false
  22. 48.
  23. 49.

    list = [2, "Caqui Coders", :community] hosts = ["Alexandre", "Claudiney",

    "Lucas"] Listas são coleções de valores que podem incluir múltiplos tipos. Listas
  24. 50.

    O Elixir implementa o tipo lista como lista ligada, o

    que faz com que acessar o tamanho da lista seja feito em um tempo linear (O(n)). Por isso é mais rápido inserir um elemento no começo da lista do que ao final dela. Listas
  25. 51.

    Listas iex> list = [3.14, :pie, "Apple"] [3.14, :pie, "Apple"]

    # Prepending (fast) iex> ["π"] ++ list ["π", 3.14, :pie, "Apple"] # Appending (slow) iex> list ++ ["Cherry"] [3.14, :pie, "Apple", "Cherry"]
  26. 52.
  27. 53.

    Tupla é uma coleção de valores ordenados. As tuplas são

    armazenadas de maneira contígua em memória, o que faz com que acessar seu tamanho seja rápido, porém modificá-la é mais custosa. Uma tupla no Elixir normalmente tem 2 ou 3 elementos. Se for necessário mais do que isso, provavelmente uma lista será melhor Tuplas
  28. 56.

    Listas de palavras chaves (keyword lists) são coleções associativas do

    Elixir. As keyword lists nada mais são do que listas de tuplas. Keyword lists
  29. 57.

    Keyword lists iex> [foo: "bar", hello: "world"] [foo: "bar", hello:

    "world"] iex> [{:foo, "bar"}, {:hello, "world"}] [foo: "bar", hello: "world"]
  30. 58.
  31. 59.

    Mapas normalmente são a escolha para armazenamento chave-valor. A diferença

    entre os mapas e as listas de palavras-chave está no fato de que os mapas permitem chaves de qualquer tipo e não seguem uma ordem. Mapas
  32. 60.

    Mapas iex> map = %{:foo => "bar", "hello" => :world}

    %{:foo => "bar", "hello" => :world} iex> map[:foo] "bar" iex> map["hello"] :world
  33. 61.

    Structs são mapas especiais com um conjunto definido de chaves

    e valores padrões. Ele deve ser definido dentro de um módulo, no qual leva o nome dele. É comum para um struct ser a única coisa definido dentro de um módulo. Structs
  34. 63.

    Structs iex> %User{} %User<name: "Sean", roles: [], ...> iex> %User{name:

    "Steve"} %User<name: "Steve", roles: [], ...> iex> %User{name: "Steve", roles: [:manager]} %User<name: "Steve", roles: [:manager]>
  35. 64.

    Structs iex> steve = %User{name: "Steve"} %User<name: "Steve", roles: [...],

    ...> iex> sean = %{steve | name: "Sean"} %User<name: "Sean", roles: [...], ...> Podemos atualizar nosso struct apenas como se fosse um mapa:
  36. 65.

    Structs iex> %{name: "Sean"} = sean %User<name: "Sean", roles: [...],

    ...> Mais importante, você pode associar estruturas contra mapas (pattern matching):
  37. 67.

    Pattern matching é uma poderosa parte de Elixir que nos

    permite procurar padrões simples em valores, estruturas de dados, e até funções.
  38. 70.

    iex> 1 = x 1 iex> 2 = x **

    (MatchError) no match of right hand side value: 1 Pattern Matching
  39. 71.
  40. 72.

    No Elixir, como em qualquer linguagem funcional, as funções são

    cidadãs de primeira classe. Significa que elas são tratadas como qualquer outro tipo de dado.
  41. 74.

    Uma função anônima é uma função que não possui nome

    (ou identificador). Elas normalmente são usadas como argumento para outras funções. Funções anônimas
  42. 75.

    iex> sum = fn (a, b) -> a + b

    end iex> sum.(2, 3) 5 iex> Enum.map([1,2,3,4], fn x -> x * x end) [1, 4, 9, 16] Funções anônimas
  43. 77.

    As funções também podem ser receber nomes e são definidas

    dentro de módulos. Podemos especificar seu nome e sua aridade (número de argumentos). Funções nomeadas
  44. 78.

    defmodule Math do def square(number) do number * number end

    end iex> Math.square(4) 16 Funções nomeadas
  45. 79.

    defmodule Math do def divide(n1 \\ 1, n2 \\ 1)

    do n1 / n2 end end iex> Math.divide 1 Funções nomeadas com argumentos padrão
  46. 80.

    O operador pipe (|>) passa o resultado de uma função

    como o primeiro parâmetro para outra função. Operador pipe
  47. 83.

    O pipe pega o resultado da esquerda e o passa

    para o lado direito. Operador pipe
  48. 86.

    Todo List • Criar um quadro • Criar itens nesse

    quadro • Marcar itens como "feito" • Marcar itens como "não feito" • Criar testes
  49. 87.