{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# IElixir - Elixir kernel for Jupyter Project\n",
    "\n",
    "<img src=\"logo.png\" title=\"Hosted by imgur.com\" style=\"margin: 0 0;\"/>\n",
    "\n",
    "---\n",
    "\n",
    "## Google Summer of Code 2015\n",
    "> Developed by [Piotr Przetacznik](https://twitter.com/pprzetacznik)\n",
    "\n",
    "> Mentored by [José Valim](https://twitter.com/josevalim)\n",
    "\n",
    "---\n",
    "## References\n",
    "\n",
    "* [Elixir language](http://elixir-lang.org/)\n",
    "* [Jupyter Project](https://jupyter.org/)\n",
    "* [IElixir sources](https://github.com/pprzetacznik/IElixir)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting Started\n",
    "\n",
    "### Basic Types\n",
    "\n",
    "<pre>\n",
    "1          # integer\n",
    "0x1F       # integer\n",
    "1.0        # float\n",
    "true       # boolean\n",
    ":atom      # atom / symbol\n",
    "\"elixir\"   # string\n",
    "[1, 2, 3]  # list\n",
    "{1, 2, 3}  # tuple\n",
    "</pre>\n",
    "\n",
    "### Basic arithmetic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[33mwarning: \u001b[0mredefining module Unless (current version defined in memory)\n",
      "  nofile:1\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{:module, Unless, <<70, 79, 82, 49, 0, 0, 6, 40, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 168, 0, 0, 0, 19, 13, 69, 108, 105, 120, 105, 114, 46, 85, 110, 108, 101, 115, 115, 8, 95, 95, 105, 110, 102, 111, 95, 95, ...>>, {:macro_unless, 2}}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "defmodule Unless do\n",
    "  def fun_unless(clause, do: expression) do\n",
    "    if(!clause, do: expression)\n",
    "  end\n",
    "\n",
    "  defmacro macro_unless(clause, do: expression) do\n",
    "    quote do\n",
    "      if(!unquote(clause), do: unquote(expression))\n",
    "    end\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "this should never be printed\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":ok"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require Unless\n",
    "\n",
    "Unless.macro_unless false, do: IO.puts \"this should never be printed\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{{:., [], [{:__aliases__, [alias: false], [:Unless]}, :macro_unless]}, [], [false, [do: {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [], [\"this should never be printed\"]}]]}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "quote do: Unless.macro_unless false, do: IO.puts \"this should never be printed\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{{:., [], [{:__aliases__, [alias: false], [:Unless]}, :fun_unless]}, [], [false, [do: {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [], [\"this should never be printed\"]}]]}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "quote do: Unless.fun_unless false, do: IO.puts \"this should never be printed\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:if, [context: Unless, import: Kernel], [{:!, [context: Unless, import: Kernel], [false]}, [do: {{:., [], [{:__aliases__, [alias: false, counter: -576460752303423480], [:IO]}, :puts]}, [], [\"this should never be printed\"]}]]}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr = quote do: Unless.macro_unless false, do: IO.puts \"this should never be printed\"\n",
    "res = Macro.expand_once(expr, __ENV__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "if(!false) do\n",
      "  IO.puts(\"this should never be printed\")\n",
      "end\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":ok"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "IO.puts Macro.to_string(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{{:., [], [{:__aliases__, [alias: false], [:Unless]}, :fun_unless]}, [], [false, [do: {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts]}, [], [\"this should never be printed\"]}]]}"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "expr = quote do: Unless.fun_unless false, do: IO.puts \"this should never be printed\"\n",
    "res = Macro.expand_once(expr, __ENV__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Unless.fun_unless(false) do\n",
      "  IO.puts(\"this should never be printed\")\n",
      "end\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":ok"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "IO.puts Macro.to_string(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "defmodule CaptureIO2 do\n",
    "  defmacro test1(do: expression) do\n",
    "    quote do\n",
    "      original_gl = Process.group_leader()\n",
    "      {:ok, capture_gl} = StringIO.open(\"\", capture_prompt: true)\n",
    "      original_err = Process.whereis(:standard_error)\n",
    "      {:ok, capture_err} = StringIO.open(\"\", capture_prompt: true)\n",
    "      \n",
    "      try do\n",
    "        Process.group_leader(self(), capture_gl)\n",
    "        Process.unregister(:standard_error)\n",
    "        Process.register(capture_err, :standard_error)\n",
    "        \n",
    "        result = unquote(expression)\n",
    "        \n",
    "        {:ok, {_, output_string}} = StringIO.close(capture_gl)\n",
    "        {_, error_string} = StringIO.contents(capture_err)\n",
    "        \n",
    "        {result, output_string, error_string}\n",
    "      after\n",
    "        Process.group_leader(self(), original_gl)\n",
    "        \n",
    "        Process.unregister(:standard_error)\n",
    "        StringIO.close(capture_err)\n",
    "        Process.register(original_err, :standard_error)\n",
    "      end\n",
    "    end\n",
    "  end\n",
    " end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[33mwarning: \u001b[0mredefining module CaptureIO2 (current version defined in memory)\n",
      "  nofile:1\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{:module, CaptureIO2, <<70, 79, 82, 49, 0, 0, 8, 72, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 155, 0, 0, 0, 17, 17, 69, 108, 105, 120, 105, 114, 46, 67, 97, 112, 116, 117, 114, 101, 73, 79, 50, 8, 95, 95, 105, 110, ...>>, {:test1, 1}}"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "defmodule CaptureIO2 do\n",
    "  defmacro test1(do: expression) do\n",
    "    quote do\n",
    "      original_gl = Process.group_leader()\n",
    "      {:ok, capture_gl} = StringIO.open(\"\", capture_prompt: true)\n",
    "      \n",
    "      original_err = Process.whereis(:standard_error)\n",
    "      {:ok, capture_err} = StringIO.open(\"\", capture_prompt: true)\n",
    "      \n",
    "      try do\n",
    "        Process.group_leader(self(), capture_gl)\n",
    "        \n",
    "        Process.unregister(:standard_error)\n",
    "        Process.register(capture_err, :standard_error)\n",
    "        \n",
    "        result = unquote(expression)\n",
    "        \n",
    "#         IO.puts(:stderr, \"teststderrgoestothelog\")\n",
    "        {:ok, {_, output_string}} = StringIO.close(capture_gl)\n",
    "        {_, error_string} = StringIO.contents(capture_err)\n",
    "        \n",
    "        IO.puts(original_gl, \"teststdio\")\n",
    "        IO.puts(original_err, \"teststderr\")\n",
    "        \n",
    "        {result, output_string, error_string}\n",
    "#       rescue\n",
    "#         e in RuntimeError -> \"RTE\"\n",
    "#         e in CompileError -> \"CE\"\n",
    "#         error ->\n",
    "#           raise(error)\n",
    "#           {:error, error}\n",
    "# #         a ->\n",
    "# #           {:a, a}\n",
    "      after\n",
    "        Process.group_leader(self(), original_gl)\n",
    "        \n",
    "        Process.unregister(:standard_error)\n",
    "        StringIO.close(capture_err)\n",
    "        Process.register(original_err, :standard_error)\n",
    "        IO.puts(\"testafter2\")\n",
    "      end\n",
    "    end\n",
    "  end\n",
    " end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "metadata": {},
   "outputs": [
    {
     "ename": "MatchError",
     "evalue": "1",
     "output_type": "error",
     "traceback": [
      "** %MatchError{term: {:error, {1, \"syntax error before: \", \"\"}}}"
     ]
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [
    {
     "ename": "MatchError",
     "evalue": "1",
     "output_type": "error",
     "traceback": [
      "** %MatchError{term: {:error, {7, \"syntax error before: \", \"\\\"2\\\"\"}}}"
     ]
    }
   ],
   "source": [
    "require CaptureIO2\n",
    "\n",
    "CaptureIO2.test1 do\n",
    "  IO.puts(\"aaa\")\n",
    "#   %{file: file, line: line} = __CALLER__\n",
    "#   File.read! \"unknown\"\n",
    "  :elixir_errors.warn 1 2 \"aaa\"\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "teststdio\n",
      "testafter2\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "teststderr\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{:ok, \"aaa\\n\", \"teststderrgoestothelog\\n\"}"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require CaptureIO2\n",
    "\n",
    "CaptureIO2.test1 do\n",
    "  IO.puts(\"aaa\")\n",
    "#   %{file: file, line: line} = __CALLER__\n",
    "#   File.read! \"unknown\"\n",
    "#   :elixir_errors.warn \"aaa\"\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:ok, \"aaa\\n\", \"\"}"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "require IElixir.CaptureIO\n",
    "\n",
    "IElixir.CaptureIO.capture(fn ->\n",
    "  IO.puts(\"aaa\")\n",
    "#   :elixir_errors.warn \"aaa\"\n",
    "#   asdf\n",
    "end)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "ename": "ArgumentError",
     "evalue": "1",
     "output_type": "error",
     "traceback": [
      "** (ArgumentError) \"argument error\""
     ]
    }
   ],
   "source": [
    "require CaptureIO2\n",
    "\n",
    "expr = CaptureIO2.capture2 1+1\n",
    "# res = Macro.expand_once(expr, __ENV__)\n",
    "# IO.puts Macro.to_string(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "ename": "MatchError",
     "evalue": "1",
     "output_type": "error",
     "traceback": [
      "** %MatchError{term: {1, 2}}"
     ]
    }
   ],
   "source": [
    "{a} = {1,2}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "25\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "IO.inspect 5 * 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "10 / 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "div(10, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "div 10, 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rem 10, 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0b1010"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "511"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0o777"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "31"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0x1F"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0e-10"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1.0e-10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "round 3.58"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "trunc 3.58"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Booleans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"true\""
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "true"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "true == false"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_boolean(true)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_boolean(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_integer(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_float(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_number(\"5.0\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Atoms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":hello"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    ":hello"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    ":hello == :world"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "true == :true"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_atom(false)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_boolean(:false)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Strings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"hellö\""
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"hellö\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"hellö world\""
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"hellö #{:world}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello\n",
      "world\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":ok"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "IO.puts \"hello\\nworld\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_binary(\"hellö\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "byte_size(\"hellö\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "String.length(\"hellö\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"HELLÖ\""
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "String.upcase(\"hellö\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Anonymous functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "#Function<12.99386804/2 in :erl_eval.expr/5>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "add = fn a, b -> a + b end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_function(add)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_function(add, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "is_function(add, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "add.(1, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "#Function<6.99386804/1 in :erl_eval.expr/5>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "add_two = fn a -> add.(a, 2) end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "add_two.(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "42"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = 42\n",
    "(fn -> x = 0 end).()\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### (Linked) Lists"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, true, 3]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [1, 2, true, 3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "length [1, 2, 3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4, 5, 6]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[1, 2, 3] ++ [4, 5, 6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, true]"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[1, true, 2, false, 3, true] -- [true, false]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hd(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, true, 3]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tl(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "ename": "ArgumentError",
     "evalue": "1",
     "output_type": "error",
     "traceback": [
      "** (ArgumentError) \"argument error\""
     ]
    }
   ],
   "source": [
    "hd []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\v\\f\\r'"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[11, 12, 13]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'hello'"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[104, 101, 108, 108, 111]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'hello' == \"hello\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tuples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:ok, \"hello\"}"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{:ok, \"hello\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuple_size {:ok, \"hello\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:ok, \"hello\"}"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuple = {:ok, \"hello\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"hello\""
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "elem(tuple, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuple_size(tuple)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:ok, \"world\"}"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "put_elem(tuple, 1, \"world\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:ok, \"hello\"}"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Lists or tuples?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3]"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list = [1|[2|[3|[]]]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3]"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[0] ++ list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list ++ [4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:ok, \"Copyright 2015 Piotr Przetacznik\\n\\n  Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\n  you may not use this file except in compliance with the License.\\n  You may obtain a copy of the License at\\n\\n      http://www.apache.org/licenses/LICENSE-2.0\\n\\n  Unless required by applicable law or agreed to in writing, software\\n  distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\n  See the License for the specific language governing permissions and\\n  limitations under the License.\\n\"}"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "File.read(\"LICENSE\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:error, :enoent}"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "File.read(\"path/to/unknown/file\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Other examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "31"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0x1F"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "175\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":ok"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 25\n",
    "b = 150\n",
    "IO.puts(a+b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:module, Math, <<70, 79, 82, 49, 0, 0, 4, 32, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 124, 0, 0, 0, 14, 11, 69, 108, 105, 120, 105, 114, 46, 77, 97, 116, 104, 8, 95, 95, 105, 110, 102, 111, 95, 95, 9, 102, ...>>, {:sum, 2}}"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "defmodule Math do\n",
    "  def sum(a, b) do\n",
    "    a + b\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Math.sum(1, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import ExUnit.CaptureIO\n",
    "capture_io(fn -> IO.write \"john\" end) == \"john\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "97"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "?a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "<<98>> == <<?b>>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "<<?g, ?o, ?\\n>> == \"go\n",
    "\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\"head\", \"body\"}"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{hlen, blen} = {4, 4}\n",
    "<<header :: binary-size(hlen), body :: binary-size(blen)>> = \"headbody\"\n",
    "{header, body}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[0m\n",
      "\u001b[7m\u001b[33m                                  IEx.Helpers                                   \u001b[0m\n",
      "\u001b[0m\n",
      "Welcome to Interactive Elixir. You are currently seeing the documentation for\n",
      "the module \u001b[36mIEx.Helpers\u001b[0m which provides many helpers to make Elixir's shell more\n",
      "joyful to work with.\n",
      "\u001b[0m\n",
      "This message was triggered by invoking the helper \u001b[36mh()\u001b[0m, usually referred to as\n",
      "\u001b[36mh/0\u001b[0m (since it expects 0 arguments).\n",
      "\u001b[0m\n",
      "You can use the \u001b[36mh/1\u001b[0m function to invoke the documentation for any Elixir module\n",
      "or function:\n",
      "\u001b[0m\n",
      "\u001b[36m    iex> h(Enum)\n",
      "    iex> h(Enum.map)\n",
      "    iex> h(Enum.reverse/1)\u001b[0m\n",
      "\u001b[0m\n",
      "You can also use the \u001b[36mi/1\u001b[0m function to introspect any value you have in the\n",
      "shell:\n",
      "\u001b[0m\n",
      "\u001b[36m    iex> i(\"hello\")\u001b[0m\n",
      "\u001b[0m\n",
      "There are many other helpers available, here are some examples:\n",
      "\u001b[0m\n",
      "  • \u001b[36mb/1\u001b[0m            - prints callbacks info and docs for a given module\n",
      "  • \u001b[36mc/1\u001b[0m            - compiles a file into the current directory\n",
      "  • \u001b[36mc/2\u001b[0m            - compiles a file to the given path\n",
      "  • \u001b[36mcd/1\u001b[0m           - changes the current directory\n",
      "  • \u001b[36mclear/0\u001b[0m        - clears the screen\n",
      "  • \u001b[36mexports/1\u001b[0m      - shows all exports (functions + macros) in a module\n",
      "  • \u001b[36mflush/0\u001b[0m        - flushes all messages sent to the shell\n",
      "  • \u001b[36mh/0\u001b[0m            - prints this help message\n",
      "  • \u001b[36mh/1\u001b[0m            - prints help for the given module, function or macro\n",
      "  • \u001b[36mi/0\u001b[0m            - prints information about the last value\n",
      "  • \u001b[36mi/1\u001b[0m            - prints information about the given term\n",
      "  • \u001b[36mls/0\u001b[0m           - lists the contents of the current directory\n",
      "  • \u001b[36mls/1\u001b[0m           - lists the contents of the specified directory\n",
      "  • \u001b[36mopen/1\u001b[0m         - opens the source for the given module or function in\n",
      "    your editor\n",
      "  • \u001b[36mpid/1\u001b[0m          - creates a PID from a string\n",
      "  • \u001b[36mpid/3\u001b[0m          - creates a PID with the 3 integer arguments passed\n",
      "  • \u001b[36mref/1\u001b[0m          - creates a Reference from a string\n",
      "  • \u001b[36mref/4\u001b[0m          - creates a Reference with the 4 integer arguments\n",
      "    passed\n",
      "  • \u001b[36mpwd/0\u001b[0m          - prints the current working directory\n",
      "  • \u001b[36mr/1\u001b[0m            - recompiles the given module's source file\n",
      "  • \u001b[36mrecompile/0\u001b[0m    - recompiles the current project\n",
      "  • \u001b[36mruntime_info/0\u001b[0m - prints runtime info (versions, memory usage, stats)\n",
      "  • \u001b[36mv/0\u001b[0m            - retrieves the last value from the history\n",
      "  • \u001b[36mv/1\u001b[0m            - retrieves the nth value from the history\n",
      "\u001b[0m\n",
      "Help for all of those functions can be consulted directly from the command line\n",
      "using the \u001b[36mh/1\u001b[0m helper itself. Try:\n",
      "\u001b[0m\n",
      "\u001b[36m    iex> h(v/0)\u001b[0m\n",
      "\u001b[0m\n",
      "To list all IEx helpers available, which is effectively all exports (functions\n",
      "and macros) in the \u001b[36mIEx.Helpers\u001b[0m module:\n",
      "\u001b[0m\n",
      "\u001b[36m    iex> exports(IEx.Helpers)\u001b[0m\n",
      "\u001b[0m\n",
      "This module also includes helpers for debugging purposes, see \u001b[36mIEx.break!/4\u001b[0m for\n",
      "more information.\n",
      "\u001b[0m\n",
      "To learn more about IEx as a whole, type \u001b[36mh(IEx)\u001b[0m.\n",
      "\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "do not show this result in output"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "h()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[33mwarning: \u001b[0mredefining module KV.Registry (current version defined in memory)\n",
      "  nofile:1\n",
      "\n",
      "\u001b[33mwarning: \u001b[0mHashDict.new/0 is deprecated, use maps and the Map module instead\n",
      "  nofile:32\n",
      "\n",
      "\u001b[33mwarning: \u001b[0mHashDict.fetch/2 is deprecated, use maps and the Map module instead\n",
      "  nofile:36\n",
      "\n",
      "\u001b[33mwarning: \u001b[0mHashDict.has_key?/2 is deprecated, use maps and the Map module instead\n",
      "  nofile:40\n",
      "\n",
      "\u001b[33mwarning: \u001b[0mHashDict.put/3 is deprecated, use maps and the Map module instead\n",
      "  nofile:44\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{:module, KV.Registry, <<70, 79, 82, 49, 0, 0, 15, 52, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 166, 0, 0, 0, 44, 18, 69, 108, 105, 120, 105, 114, 46, 75, 86, 46, 82, 101, 103, 105, 115, 116, 114, 121, 8, 95, 95, 105, ...>>, {:handle_cast, 2}}"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "defmodule KV.Registry do\n",
    "  use GenServer\n",
    "\n",
    "  ## Client API\n",
    "\n",
    "  @doc \"\"\"\n",
    "  Starts the registry.\n",
    "  \"\"\"\n",
    "  def start_link(opts \\\\ []) do\n",
    "    GenServer.start_link(__MODULE__, :ok, opts)\n",
    "  end\n",
    "\n",
    "  @doc \"\"\"\n",
    "  Looks up the bucket pid for `name` stored in `server`.\n",
    "\n",
    "  Returns `{:ok, pid}` if the bucket exists, `:error` otherwise.\n",
    "  \"\"\"\n",
    "  def lookup(server, name) do\n",
    "    GenServer.call(server, {:lookup, name})\n",
    "  end\n",
    "\n",
    "  @doc \"\"\"\n",
    "  Ensures there is a bucket associated to the given `name` in `server`.\n",
    "  \"\"\"\n",
    "  def create(server, name) do\n",
    "    GenServer.cast(server, {:create, name})\n",
    "  end\n",
    "\n",
    "  ## Server Callbacks\n",
    "\n",
    "  def init(:ok) do\n",
    "    {:ok, HashDict.new}\n",
    "  end\n",
    "\n",
    "  def handle_call({:lookup, name}, _from, names) do\n",
    "    {:reply, HashDict.fetch(names, name), names}\n",
    "  end\n",
    "\n",
    "  def handle_cast({:create, name}, names) do\n",
    "    if HashDict.has_key?(names, name) do\n",
    "      {:noreply, names}\n",
    "    else\n",
    "      {:ok, bucket} = KV.Bucket.start_link()\n",
    "      {:noreply, HashDict.put(names, name, bucket)}\n",
    "    end\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[#Function<2.42286359/1 in ExUnit.start/1>]"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ExUnit.start()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{:module, KV.RegistryTest, <<70, 79, 82, 49, 0, 0, 15, 132, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 232, 0, 0, 0, 47, 22, 69, 108, 105, 120, 105, 114, 46, 75, 86, 46, 82, 101, 103, 105, 115, 116, 114, 121, 84, 101, 115, 116, ...>>, {:\"test spawns buckets\", 1}}"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "defmodule KV.RegistryTest do\n",
    "  use ExUnit.Case, async: true\n",
    "\n",
    "  setup do\n",
    "    {:ok, registry} = KV.Registry.start_link\n",
    "    {:ok, registry: registry}\n",
    "  end\n",
    "\n",
    "  test \"spawns buckets\", %{registry: registry} do\n",
    "    assert KV.Registry.lookup(registry, \"shopping\") == :error\n",
    "\n",
    "    KV.Registry.create(registry, \"shopping\")\n",
    "    assert {:ok, bucket} = KV.Registry.lookup(registry, \"shopping\")\n",
    "\n",
    "    KV.Bucket.put(bucket, \"milk\", 1)\n",
    "    assert KV.Bucket.get(bucket, \"milk\") == 1\n",
    "  end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Elixir",
   "language": "Elixir",
   "name": "ielixir"
  },
  "language_info": {
   "codemirror_mode": "elixir",
   "file_extension": "ex",
   "mimetype": "text/x-elixir",
   "name": "elixir",
   "nbconvert_exporter": "",
   "pygments_lexer": "elixir",
   "version": "1.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
