Powered by AppSignal & Oban Pro

Chap 2

JKBook/chap2.livemd

Chap 2

Section

This notebook contains the code and exercises I type for the book https://pragprog.com/titles/jkelixir/advanced-functional-programming-with-elixir/


defprotocol Fun.Eq do
  @fallback_to_any True

  def eq?( a , b )

  def not_eq?(a,b)
  
end

defimpl Fun.Eq, for: Any do
  def eq?(a,b), do: a == b
  def not_eq?(a,b), do: a != b
    
end

Patron module

defmodule Fun.Patron do
 
  defstruct id: nil,
            name: nil,
            age: 0,
            height: 0,
            ticket_tier: :basic,
            fast_passes: [],
            reward_points: 0,
            likes: [],
            dislikes: []

  def make(name, age, height, opts \\ [])
      when is_bitstring(name) and is_integer(age) and is_integer(height) and age > 0 and
             height > 0 do
    %__MODULE__{
      id: :erlang.unique_integer([:positive]),
      name: name,
      age: age,
      height: height,
      ticket_tier: Keyword.get( opts , :ticket_tier , :basic),
      fast_passes: Keyword.get(opts , :fast_passes , []) , 
      reward_points: Keyword.get(opts , :reward_points , 0),
      likes: Keyword.get(opts , :fast_passes , []),
      dislikes: Keyword.get(opts , :fast_passes , []),
         
    }
  end

  def change(%__MODULE__{} = patron , changes) when is_map(changes) do
    changes = Map.delete(changes , :id)

    struct( patron, changes) 
  end
end

defimpl Fun.Eq, for: Fun.Patron do 
  alias Fun.Eq
  alias Fun.Patron
  def eq?( %Patron{ id: id1 } , %Patron{ id: id2} ), do: Eq.eq?(id1 , id2)
  def not_eq?( %Patron{ id: id1 } , %Patron{ id: id2} ), do: Eq.not_eq?(id1 , id2)
  
end

Ride module

defmodule Fun.Ride do
    defstruct id: nil,
            name: "Unknown Ride",
            min_age: 0,
            min_height: 0,
            wait_time: 0,
            online: true,
            tags: []

  def make(name, opts \\ [] ) when is_binary(name) do
    %__MODULE__{
      name: name, 
      min_age: Keyword.get(opts, :min_age , 0),
      min_height: Keyword.get(opts, :min_height , 0),
      wait_time: Keyword.get(opts, :wait_time , 0),
      online: Keyword.get(opts, :online , true),
      tags: Keyword.get(opts, :tags , []),

    }
  end

end

Pass module

defmodule Fun.Pass do
  alias Fun.Ride
  
  defstruct id: nil,
    ride: nil,
    time: nil

  def make( %Ride{} = ride, %DateTime{} = time) do 
    %__MODULE__{
      id: :erlang.unique_integer([:positive]),
      ride: ride,
      time: time
    }
  end
  
end

Testing Things

alice = Fun.Patron.make("alice"  , 15 , 100 )
alice_b = Fun.Patron.change(alice , %{ ticket_tier: :premium} )
alice == alice_b