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. Elixir Introdução a Programação Funcional com

  2. Lucas Santos Software Developer lslm lucassantos11

  3. None
  4. Check our job openings! careers.plataformatec.com.br

  5. None
  6. None
  7. Programação Funcional?

  8. Orientação a Objetos vs. Programação Funcional

  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)"
  10. Vamos a um exemplo...

  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
  12. rex = Dog.new('Rex', 'ball') rex.favorite_toy # ball rex.change_favorite_toy('rope') rex.favorite_toy #

    rope
  13. Lidamos com estados e manipulação dos mesmos.

  14. Programação Funcional foca na avaliação de funções e transformação de

    dados por meio delas
  15. Linguagem imperativa vs. linguagem declarativa

  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
  17. A programação imperativa foca no como uma tarefa deve ser

    realizada, especificando o passo-a-passo.
  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.
  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
  20. A programação declarativa foca no que deve ser feito.

  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
  22. Parte 1: O básico da programação funcional

  23. Programação Funcional é o processo de construção de software utilizando

    composição de funções.
  24. Funções Puras

  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).
  26. Math.cos(x) Math.sum(x,y)

  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
  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
  29. Composição

  30. Composição de funções é uma forma de combinar funções simples

    para construir outras mais complexas.
  31. Exemplo da palestra de Scott Wlaschin: Functional programming design patterns

    (https://vimeo.com/113588389)
  32. Exemplo da palestra de Scott Wlaschin: Functional programming design patterns

    (https://vimeo.com/113588389)
  33. Exemplo da palestra de Scott Wlaschin: Functional programming design patterns

    (https://vimeo.com/113588389)
  34. Exemplo da palestra de Scott Wlaschin: Functional programming design patterns

    (https://vimeo.com/113588389)
  35. Web application HTTP request HTTP response Exemplo da palestra de

    Scott Wlaschin: Functional programming design patterns (https://vimeo.com/113588389)
  36. Imutabilidade

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

    ter seus estados alterados depois de criados.
  38. int s = 0; for (int index = 0; index

    < data.Length; index++){ s += data[index]; } Estado sendo alterado
  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
  40. Parte 2: Introdução ao Elixir

  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.
  42. Tipos básicos

  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
  44. Inteiros, pontos flutuantes, booleanos e strings são basicamente os mesmos

    de qualquer outra linguagem de programação.
  45. Átomos Átomo é um tipo de dado cujo o valor

    é o seu nome. iex> :foo :foo iex> :foo == :bar false
  46. Coleções

  47. Listas, tuplas, keyword lists e mapas são tipos de coleções

    do Elixir
  48. Listas

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

    "Lucas"] Listas são coleções de valores que podem incluir múltiplos tipos. Listas
  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
  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"]
  52. Tuplas

  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
  54. Tuplas { 1, 2 } { :ok, :live_started, "YouTube" }

    { :error, :enoent }
  55. Keyword Lists

  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
  57. Keyword lists iex> [foo: "bar", hello: "world"] [foo: "bar", hello:

    "world"] iex> [{:foo, "bar"}, {:hello, "world"}] [foo: "bar", hello: "world"]
  58. Mapas

  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
  60. Mapas iex> map = %{:foo => "bar", "hello" => :world}

    %{:foo => "bar", "hello" => :world} iex> map[:foo] "bar" iex> map["hello"] :world
  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
  62. Structs defmodule User do defstruct name: "Sean", roles: [] end

  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]>
  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:
  65. Structs iex> %{name: "Sean"} = sean %User<name: "Sean", roles: [...],

    ...> Mais importante, você pode associar estruturas contra mapas (pattern matching):
  66. Pattern Matching

  67. Pattern matching é uma poderosa parte de Elixir que nos

    permite procurar padrões simples em valores, estruturas de dados, e até funções.
  68. iex> x = 1 1 Pattern Matching

  69. iex> 1 = x 1 Pattern Matching

  70. iex> 1 = x 1 iex> 2 = x **

    (MatchError) no match of right hand side value: 1 Pattern Matching
  71. Funções

  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.
  73. Funções anônimas

  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
  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
  76. Funções nomeadas

  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
  78. defmodule Math do def square(number) do number * number end

    end iex> Math.square(4) 16 Funções nomeadas
  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
  80. O operador pipe (|>) passa o resultado de uma função

    como o primeiro parâmetro para outra função. Operador pipe
  81. foo(bar(baz(new_function(other_function())))) Operador pipe

  82. other_function() |> new_function() |> baz() |> bar() |> foo() Operador

    pipe
  83. O pipe pega o resultado da esquerda e o passa

    para o lado direito. Operador pipe
  84. iex> "Elixir rocks" |> String.upcase () |> String.split () ["ELIXIR",

    "ROCKS"] Operador pipe
  85. Let's play

  86. Todo List • Criar um quadro • Criar itens nesse

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