Functional programming concepts

Igor Kapkov, Evil Martians

Functional programming concepts

Examples in Elixir

Igas

Igor Kapkov

Evil Martians

@igasgeek / [email protected]

Why we ♥ Erlang

Why we'll ♥ Elixir

Design Goals

Concepts

Immutability

      var = 1;
      process(var);
      println(var);
    

Immutability

Immutability: example

      iex> list = [1, 2, 3]
      [1, 2, 3]
    
      iex> reversed = Enum.reverse(list)
      [3, 2, 1]
    
      iex> list
      [1, 2, 3]
    

Immutability: Performance & GC

      iex> list1 = [2, 1]
      [2, 1]
    
      iex> list2 = [3 | list1]
      [3, 2, 1]
    

Pattern matching: Math

      2x + 3 = 5
    
      iex> x = 1
      1
    
      iex> 2 * x + 3
      5
    
      iex> 5 = 2 * x + 3
      5
    

Pattern matching: Match Operator

      iex> x = 1
      1
    
      iex> 1 = x
      1
    
      iex> 2 = x
      ** (MatchError) no match of right hand side value: 1
    

Pattern matching: Match Operator

      iex> {name, age} = {"John Doe", 27}
      {"John Doe", 27}
    
      iex> name
      "John Doe"
    
      iex> age
      27
    

Pattern matching: _

      iex> {_, _, age} = {"John", "Doe", 27}
      {"John Doe", 27}
    
      iex> age
      27
    

Pattern matching: eql example

      iex> {x, x} = {1, 1}
      {1, 1}
    
      iex> {x, x} = {1, 2}
      ** (MatchError) no match of right hand side value: {1, 2}
    

Pattern matching: SSA & Pin operator

      iex> x = 1
      1
    
      iex> x = 2
      2
    
      iex> ^x = 2
      2
    
      iex> ^x = 3
      ** (MatchError) no match of right hand side value: 3
    

Pattern matching: Lists

      iex> [head|tail] = [1, 2, 3]
      [1, 2, 3]
    
      iex> head
      1
    
      iex> tail
      [2, 3]
    

Pattern matching: Conditional matching

      iex> {:ok, file} = File.open(".vimrc")
      {:ok, #PID<0.72.0>}
    

Pattern matching: example

      %User{confirmed: false, premium: false}
    
      function check_user(user) {
        if(!user.present?) {
          redirect_to("/sign_in")
        } else {
          if(!user.confirmed?) {
            redirect_to("/confirmation")
          } elseif(!user.premium?) {
            redirect_to("/pay")
          }
        }
      }
    

Pattern matching: example

      def check_user(nil), do: redirect_to("/sign_in")
    
    
def check_user(%User{confirmed: false}), do: redirect_to("/confirmation")
    
def check_user(%User{premium: false}), do: redirect_to("/pay")
    
def check_user(user), do: user

Higher-order functions: Function type

      fn
        args1 -> body1
        args2 -> body2
      end
    

Higher-order functions: eql example

      iex> eql = fn
      ...>   (a, a) -> true
      ...>   (_, _) -> false
      ...> end
    
      iex> eql.(1,1)
      true
    
      iex> eql.(1,2)
      false
    

Higher-order functions: Currying & Closure

      iex> sum = fn(a) ->
      ...>   fn(b) -> a + b end
      ...> end
      #Function<6.90072148/1 in :erl_eval.expr/5>
    
      iex> sum.(1).(3)
      4
    
      iex> add2 = sum.(2)
      #Function<6.90072148/1 in :erl_eval.expr/5>
    
      iex> add2.(4)
      6
    

Higher-order functions: Function capturing

      iex> Enum.map([1, 2, 3], fn x -> x * x end)
      [1, 4, 9]
    
      iex> Enum.sort [1, 2, 3], &( &2 < &1 )
      [3, 2, 1]
    
      iex> Enum.all? [:a, :b, :c], &is_atom(&1)
      true
    
      iex> Enum.map  ["a", "B", "c"], &String.upcase &1
      ["A", "B", "C"]
    
      iex> Enum.map  ["a", "B", "c"], &String.to_atom/1
      [:a, :B, :c]
    

Recursion

      defmodule Lst do
        def size([]), do: 0
        def size([_head|tail]), do: 1 + size(tail)
      end
    
      iex> Lst.size([])
      0
    
      iex> Lst.size([1,2,3,4,5])
      5
    

Functional programming concepts

Igor Kapkov, Evil Martians