Skip to content

Instantly share code, notes, and snippets.

@colinbankier
Last active August 3, 2016 05:21
Show Gist options
  • Save colinbankier/8783f999ba7335f329781190c58eff16 to your computer and use it in GitHub Desktop.
Save colinbankier/8783f999ba7335f329781190c58eff16 to your computer and use it in GitHub Desktop.

Elixir in Action Part 1

Elixir News

Recap - Concurrency

https://gist.github.com/colinbankier/a3f2eb7642b94c0d610a

Elixir in Action

Elixir in Action, by Sasa Juric https://www.manning.com/books/elixir-in-action

We'll work through the hands-on excerises from this book, would build a ToDo server application. The concept of the application is simple enough. The basic version of the to-do list will support the following features:

  • Creating a new data abstraction
  • Adding new entries
  • Querying the abstraction We'll continue adding features and by the end we’ll have a fully working distributed web server that can manage a large number of to-do lists.

Overview

  • Todo list data abstraction
  • Server Processes
    • Todo generic server process
    • GenServer powered Todo server
  • Building a concurrent system
    • Managing multiple Todo lists
    • Persisting data
    • Analysing and addressing bottlenecks
  • Fault tolerance
    • Errors in concurrent systems
    • Supervisors and Supervision trees
    • Isolating error effects
  • Sharing state
    • Single process bottlenecks
    • ETS Tables
  • Production
    • Working with components
    • Building and running the distributed system

Abstracting with Modules

First, we'll create a basic data structure for our todo lists, and a module for functions to manipulate it. Here is an example usage:

iex(1)> todo_list =
TodoList.new |>
TodoList.add_entry({2013, 12, 19}, "Dentist") |>
TodoList.add_entry({2013, 12, 20}, "Shopping") |>
TodoList.add_entry({2013, 12, 19}, "Movies")

iex(2)> TodoList.entries(todo_list, {2013, 12, 19})
["Movies", "Dentist"]

iex(3)> TodoList.entries(todo_list, {2013, 12, 18})
[]

First, create a new project:

mix new todo

Let's do a little bit of TDD as we go, so start a new test in test/todo_list_test.exs Here is a test that does what our example snippet says, but I'm going to represent an entry as a Map with date and title attributes:

defmodule TodoListTest do
  use ExUnit.Case

  test "should add todos to a todo list" do
    todo_list =
      TodoList.new |>
      TodoList.add_entry(%{date: {2013, 12, 19}, title: "Dentist"}) |>
      TodoList.add_entry(%{date: {2013, 12, 20}, title: "Shopping"}) |>
      TodoList.add_entry(%{date: {2013, 12, 19}, title: "Movies"})

    assert TodoList.entries(todo_list, {2013, 12, 19}) == [
      %{date: {2013, 12, 19}, title: "Movies"},
      %{date: {2013, 12, 19}, title: "Dentist"}
    ]
    assert TodoList.entries(todo_list, {2013, 12, 18}) == []
  end
end

Then create TodoList module in lib/todo_list.ex Looking at our test, we can see a todo list is some of mapping from dates to entries, so we'll use a Map as our internal represention.

defmodule TodoList do
  def new, do: %{}
end

Next, we'll implement the add_entry/3 function. It needs to add the entry to the entry list for the specified date, and also handle the case where no entries exist yet for that date. Turns out we can do with one call to Map.update/4.

def add_entry(todo_list, date, title) do
  Map.update(
    todo_list,
    date,
    [title],
    fn(titles) -> [title | titles] end
  )
end

Then, we'll add the entries function:

def entries(todo_list, date) do
  Map.get(todo_list, date, [])
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment