{"id":13682044,"url":"https://github.com/dwyl/learn-elixir","last_synced_at":"2025-05-15T10:02:14.226Z","repository":{"id":37743202,"uuid":"75262873","full_name":"dwyl/learn-elixir","owner":"dwyl","description":":droplet: Learn the Elixir programming language to build functional, fast, scalable and maintainable web applications!","archived":false,"fork":false,"pushed_at":"2024-10-07T13:29:09.000Z","size":5297,"stargazers_count":1657,"open_issues_count":129,"forks_count":109,"subscribers_count":176,"default_branch":"main","last_synced_at":"2025-04-12T03:44:33.992Z","etag":null,"topics":["beginner","beginner-friendly","elixir","elixir-lang","tutorial","tutorial-code"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dwyl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-01T06:33:44.000Z","updated_at":"2025-04-06T09:38:51.000Z","dependencies_parsed_at":"2024-01-14T15:26:51.274Z","dependency_job_id":"72fa8453-8e19-4222-9cee-cea67562fac5","html_url":"https://github.com/dwyl/learn-elixir","commit_stats":{"total_commits":191,"total_committers":34,"mean_commits":5.617647058823529,"dds":0.6439790575916231,"last_synced_commit":"e7c3df9a12c31052821577a9b2caac03555e760e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Flearn-elixir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Flearn-elixir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Flearn-elixir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dwyl%2Flearn-elixir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dwyl","download_url":"https://codeload.github.com/dwyl/learn-elixir/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319716,"owners_count":22051072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beginner","beginner-friendly","elixir","elixir-lang","tutorial","tutorial-code"],"created_at":"2024-08-02T13:01:39.650Z","updated_at":"2025-05-15T10:02:13.288Z","avatar_url":"https://github.com/dwyl.png","language":"Elixir","readme":"\u003cdiv align=\"center\"\u003e\n\n# Learn ![elixir logo](http://elixir-lang.org/images/logo/logo.png \"Elixir Logo\")\n\n\u003c/div\u003e\n\n- [Learn ](#learn-)\n  - [_Why_?](#why)\n    - [Key Advantages](#key-advantages)\n  - [_What_?](#what)\n    - [Video Introductions](#video-introductions)\n  - [_How_?](#how)\n    - [Installation:](#installation)\n      - [Mac:](#mac)\n      - [Ubuntu:](#ubuntu)\n      - [Windows:](#windows)\n      - [Livebook:](#livebook)\n  - [Learn Elixir](#learn-elixir)\n  - [Commands](#commands)\n  - [Basic Types](#basic-types)\n    - [Numbers](#numbers)\n    - [Booleans](#booleans)\n    - [Truthiness: truthy and falsy values](#truthiness-truthy-and-falsy-values)\n    - [Atoms](#atoms)\n    - [Strings](#strings)\n    - [Lists](#lists)\n    - [Tuples](#tuples)\n    - [Lists or Tuples?](#lists-or-tuples)\n  - [Functions and Modules](#functions-and-modules)\n    - [Anonymous functions](#anonymous-functions)\n    - [Modules](#modules)\n  - [Create Your First `Elixir` Project](#create-your-first-elixir-project)\n    - [Initialise](#initialise)\n    - [Edit `animals.ex`](#edit-animalsex)\n    - [Run the Code](#run-the-code)\n    - [Define Functions](#define-functions)\n    - [Extend Functions](#extend-functions)\n    - [Add More Functions!](#add-more-functions)\n    - [Pattern Matching _Example_](#pattern-matching-example)\n    - [Save Data to File](#save-data-to-file)\n    - [Retrieve Data from File](#retrieve-data-from-file)\n      - [Pipe Operator](#pipe-operator)\n  - [Documentation](#documentation)\n  - [Testing](#testing)\n  - [Formatting](#formatting)\n  - [Publishing](#publishing)\n    - [Congratulations!](#congratulations)\n    - [Want _More_?](#want-more)\n  - [Data Structures](#data-structures)\n    - [Maps](#maps)\n      - [Updating a value inside a map](#updating-a-value-inside-a-map)\n  - [Processes](#processes)\n    - [Spawning a process](#spawning-a-process)\n    - [Sending messages between processes](#sending-messages-between-processes)\n    - [Concurrency](#concurrency)\n  - [tl;dr](#tldr)\n  - [Further resources:](#further-resources)\n\n\u003cbr /\u003e\n\n## _Why_?\n\n### Key Advantages\n\n- **Scalability**\n- **Speed**\n- **Compiled** and run on the **Erlang VM** (\"BEAM\"). [(Renowned for efficiency)](http://stackoverflow.com/questions/16779162/what-kind-of-virtual-machine-is-beam-the-erlang-vm)\n- Much better [\"garbage collection\"](http://searchstorage.techtarget.com/definition/garbage-collection) than virtually any other VM\n- Many tiny processes (as opposed to \"threads\"\n  which are more difficult to manage)\n- **Functional** language with [dynamic](https://www.sitepoint.com/typing-versus-dynamic-typing/) typing\n- [Immutable data](https://benmccormick.org/2016/06/04/what-are-mutable-and-immutable-data-structures-2/) so [\"state\"](http://softwareengineering.stackexchange.com/questions/235558/what-is-state-mutable-state-and-immutable-state) is always **predictable**! \u003cbr /\u003e\n  ![image](https://cloud.githubusercontent.com/assets/194400/22413420/8a538bc2-e6af-11e6-80fd-209deb887820.png) \u003cbr /\u003e\n- **High reliability, availability and fault tolerance** (_because of Erlang_)\n  means apps built with **`Elixir`** are run in production for **years**\n  without any \"_downtime_\"!\n- Real-time web apps are \"_easy_\"\n  (_or at least easier than many other languages!_) as **WebSockets \u0026 streaming** are baked-in\n\nThings _will_ go wrong with\ncode, and **`Elixir`** provides supervisors which describe how to restart parts of\nyour system when things don't go as planned.\n\n## _What_?\n\n[_\"Elixir is a dynamic, functional language designed for building scalable and\nmaintainable applications.\"_](http://elixir-lang.org/)\n\n### Video Introductions\n\nIf you have the time, these videos give a nice contextual introduction into what **`Elixir`** is, what it's used for and how it works:\n\n\u003c!-- note we should update this once we have\nmade our *own* intro to **`Elixir`** vid! --\u003e\n\n- Code School's [Try Elixir](https://www.codeschool.com/courses/try-elixir), 3 videos (25mins :movie_camera: plus exercises, totalling 90mins). The 'Try' course is free (there is an extended paid for course).\n- Pete Broderick's [Intro to Elixir](https://youtu.be/lly-1UYmnFI) (41 mins :movie_camera:)\n- Jessica Kerr's [Elixir Should Take Over the World](https://youtu.be/X25xOhntr6s) (58 mins :movie_camera:)\n\nNot a video learner? Looking for a specific learning? https://elixirschool.com/ is an excellent, free, open-source resource that explains all things **`Elixir`** :book: :heart:.\n\n## _How_?\n\nBefore you learn **`Elixir`** as a language you will need to have it installed on your machine.\n\nTo do so you can go to\nhttp://elixir-lang.org/install.html or follow our guide here:\n\n### Installation:\n\n#### Mac:\n\nUsing the [Homebrew](https://brew.sh/) package manager:\n`brew install elixir`\n\n\u003e If you have any trouble with `ssl` when running an `Elixir` App on your `Mac`,\n\u003e see: \n\u003e [`/install-mac.md`](https://github.com/dwyl/learn-elixir/blob/main/install-mac.md)\n\n\n#### Ubuntu:\n\n- **Add the Erlang Solutions repo**:\n\n```\nwget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb \u0026\u0026 sudo dpkg -i erlang-solutions_2.0_all.deb\n```\n\n- **Run**: `sudo apt-get update`\n- **Install the Erlang/OTP platform and all of its applications**:\n  `sudo apt-get install esl-erlang`\n- **Install Elixir**: `sudo apt-get install elixir`\n\n\n#### Windows:\n\n- **Web installer**\n  \n  - **Erlang installer**\n  - Download the Windows installer for Erlang (32 or 64-bit): [erlang.org/downloads](https://www.erlang.org/downloads.html)\n  - Click next, next,..., close\n \n  - **Elixir installer**\n  - Download the Elixir installer matching your Erlang version: [github.com/elixir-lang/elixir/releases/download/v1.17.3]https://github.com/elixir-lang/elixir/releases/download/v1.17.3/elixir-otp-27.exe\n  - Click next, install, ..., close\n \n  - **Check to see if successful**\n  - Run `elixir -v` in your terminal\n  - Should output Erlang \u0026 Elixir versions\n    \n\n- **Chocolatey** (_Package Manager_)\n\n```\nchoco install elixir\n```\n\n#### Livebook:\n\n- Easy peasy if you have `Elixir` installed. Just click below\n\n👉 [\u003cimg width=\"326\" alt=\"Screenshot 2023-01-13 at 10 15 23\" src=\"https://user-images.githubusercontent.com/6793008/212283403-116dbf5c-eea4-4c16-88df-b9aba86e209a.png\"\u003e](https://livebook.dev/)\n\nOnce `Livebook` installed on your machine, just click on the button below (or fork and run it):\n\n[![Run in Livebook](https://livebook.dev/badge/v1/blue.svg)](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2Fdwyl%2Flearn-elixir%2Fblob%2Fmain%2Flearn-elixir-on-livebook.livemd)\n\n- Alternatively, you can run a `Docker` image, no need to install `Elixir` or `Livebook`. Launch `Docker` and run the `Livebook` image:\n\n```\ndocker run -p 8080:8080 -p 8081:8081 --pull always -e LIVEBOOK_PASSWORD=\"securesecret\" livebook/livebook\n```\n\nand in another terminal you launch the browser (you will need to authneticate with \"securesecret\") with the command:\n\n```\nopen http://localhost:8080/import?url=https://github.com/dwyl/learn-elixir/blob/main/learn-elixir-on-livebook.livemd\n```\n\n- Finally, if you don't have `Docker` nor `Elixir` and `Livebook` installed, you can run a remote version in the cloud. Follow this!\n\nYou (**right**-)click on the grey button **\"Run in Livebook\"** below.\n\n:heavy_exclamation_mark: You **right-click\"** to keep this reminder page open 😉 because you will need to remember to do 2 things:\n\n1. firstly, look at the bottom for the link \"see source\" as showed below, 🤔, and click.\n\n\u003cimg width=\"355\" alt=\"Screenshot 2023-01-13 at 10 23 14\" src=\"https://user-images.githubusercontent.com/6793008/212285838-96ff4672-e36a-4a89-8efa-dee53a32a405.png\"\u003e\n\n2. and finally, select the file [dwyl-learn-elixir.livemd]. It should be printed in green, and \"join session\". 🤗\n\nHappy learning! 🥳\n\nThis links to the remote Livebook: 👉\n[![Run in Livebook](https://livebook.dev/badge/v1/gray.svg)](https://livebook.dev/run?url=https%3A%2F%2Fdwyl-learn-elixir.fly.dev%2F)\n\n## Learn Elixir\n\n## Commands\n\n- After installing **`Elixir`** you can open the interactive shell by typing `iex`.\n  This allows you to type in any **`Elixir`** expression and see the result in the terminal.\n\n- Type in `h` followed by the `function` name at any time to see documentation information about any given built-in function and how to use it. E.g If you type `h round` into the (iex) terminal you should see\n  something like this:\n\n![elixir-h](https://cloud.githubusercontent.com/assets/14013616/20860273/fc801b14-b96b-11e6-9b17-7e26666d5d94.png)\n\n- Typing `i` followed by the value name will give you information about a value in your code:\n\n![elixir-i](https://cloud.githubusercontent.com/assets/14013616/20860322/3c01d984-b96d-11e6-8cc4-a46c8657f5b4.png)\n\n## Basic Types\n\nThis section brings together the key information from Elixir's\n[Getting Started](http://elixir-lang.org/getting-started/basic-types.html)\ndocumentation and multiple other sources. It will take you through some examples to practice using and familiarise yourself with Elixir's 7 basic types.\n\nElixir's 7 basic types:\n\n- `integers`\n- `floats`\n- `booleans`\n- `atoms`\n- `strings`\n- `lists`\n- `tuples`\n\n### Numbers\n\nType `1 + 2` into the terminal (after opening `iex`):\n\n```elixir\niex\u003e 1 + 2\n3\n```\n\nMore examples:\n\n```elixir\niex\u003e 5 * 5\n25\niex\u003e 10 / 2\n5.0\n\n# When using the `/` with two integers this gives a `float` (5.0).\n# If you want to do integer division or get the division remainder\n# you can use the `div` or `rem` functions\niex\u003e div(10, 2)\n5\niex\u003e div 10, 2\n5\niex\u003e rem 10, 3\n1\n```\n\n### Booleans\n\nElixir supports `true` and `false` as booleans.\n\n```elixir\niex\u003e true\ntrue\niex\u003e false\nfalse\n\niex\u003e is_boolean(true)\ntrue\niex\u003e is_boolean(1)\nfalse\n```\n\n### Truthiness: truthy and falsy values\n\nBesides the booleans `true` and `false` **`Elixir`** also has the\nconcept of a \"truthy\" or \"falsy\" value.\n\n- a value is truthy when it is neither `false` nor `nil`\n- a value is falsy when it is `false` or `nil`\n\nElixir has functions, like `and/2`, that _only_ work with\nbooleans, but also functions that work with these\ntruthy/falsy values, like `\u0026\u0026/2` and `!/1`.\n\nThe syntax `\u003cfunction_name\u003e/\u003cnumber\u003e` is the convention\nused in Elixir to identify a function named\n`\u003cfunction_name\u003e` that takes `\u003cnumber\u003e` parameters.\nThe value `\u003cnumber\u003e` is also referred to as the function\n[arity](https://en.wikipedia.org/wiki/Arity).\nIn Elixir each function is identified univocally both by\nits name and its arity. More information can be found [here](https://culttt.com/2016/05/02/understanding-function-arity-elixir/).\nWe can check the truthiness of a value by using the `!/1`\nfunction twice.\n\nTruthy values:\n\n```elixir\niex\u003e !!true\ntrue\niex\u003e !!5\ntrue\niex\u003e !![1,2]\ntrue\niex\u003e !!\"foo\"\ntrue\n```\n\nFalsy values (of which there are exactly two):\n\n```elixir\niex\u003e !!false\nfalse\niex\u003e !!nil\nfalse\n```\n\n### Atoms\n\nAtoms are constants where their name is their own value\n(some other languages call these Symbols).\n\n```elixir\niex\u003e :hello\n:hello\niex\u003e :hello == :world\nfalse\n```\n\n`true` and `false` are actually atoms in Elixir\n\nNames of _modules_ in **`Elixir`** are also atoms. `MyApp.MyModule`\nis a valid atom, even if no such module has been declared yet.\n\n```elixir\niex\u003e is_atom(MyApp.MyModule)\ntrue\n```\n\nAtoms are also used to reference modules from Erlang libraries,\nincluding built-in ones.\n\n```elixir\niex\u003e :crypto.strong_rand_bytes 3\n\u003c\u003c23, 104, 108\u003e\u003e\n```\n\nOne popular use of atoms in **`Elixir`** is to use them as messages\nfor [pattern matching](https://en.wikipedia.org/wiki/Pattern_matching).\nLet's say you have a function which processes an `http` request.\nThe outcome of this process is either going to be a success or an error.\nYou could therefore use atoms to indicate whether\nor not this process is successful.\n\n```elixir\ndef process(file) do\n  lines = file |\u003e split_lines\n\n  case lines do\n    nil -\u003e\n      {:error, \"failed to process file\"}\n    lines -\u003e\n      {:ok, lines}\n  end\nend\n```\n\nHere we are saying that the method,\n`process/1` will return a [tuple](#) response.\nIf the result of our process is successful, it will return `{:ok, lines}`,\nhowever if it fails (e.g. returns nil) then it will return an error.\nThis will allows us to _pattern_ match on this result.\n\n```elixir\n{:ok, lines} = process('text.txt')\n```\n\nThus, we can be sure that we will always have the lines returned to us\nand never a _nil_ value (because it will throw an error).\nThis becomes extremely useful when piping multiple methods together.\n\n### Strings\n\nStrings are surrounded by double quotes.\n\n```elixir\niex\u003e \"Hello World\"\n\"Hello world\"\n\n# You can print a string using the `IO` module\niex\u003e IO.puts \"Hello world\"\n\"Hello world\"\n:ok\n```\n\n### Lists\n\nElixir uses square brackets to make a list.\n\n```elixir\niex\u003e myList = [1,2,3]\niex\u003e myList\n[1,2,3]\n\niex\u003e length(myList)\n3\n\n# concatenating lists together\niex\u003e [1, 2, 3] ++ [4, 5, 6]\n[1, 2, 3, 4, 5, 6]\n\n# removing items from a list\niex\u003e [1, true, 2, false, 3, true] -- [true, false]\n[1, 2, 3, true]\n```\n\nLists are [enumerable](https://github.com/dwyl/learn-elixir/issues/39) and can use the [Enum](https://hexdocs.pm/elixir/Enum.html)\nmodule to perform iterative functions such as mapping.\n\n### Tuples\n\nElixir uses curly brackets to make a tuple.\n\nTuples are similar to lists but are\n[not suited to data sets that need to be updated or added to regularly](#lists-or-tuples).\n\n```elixir\niex\u003e tuple = {:ok, \"hello\"}\n{:ok, \"hello\"}\n\n# get element at index 1\niex\u003e elem(tuple, 1)\n\"hello\"\n\n# get the size of the tuple\niex\u003e tuple_size(tuple)\n2\n```\n\nTuples are [not enumerable](https://github.com/dwyl/learn-elixir/issues/39) and there are far fewer functions available\nin the [Tuple](http://elixir-lang.org/docs/v1.0/elixir/Tuple.html) module. You can reference tuple values by index but [you cannot iterate over them](https://github.com/dwyl/learn-elixir/issues/39).\nIf you must treat your tuple as a list,\nthen convert it using `Tuple.to_list(your_tuple)`\n\n### Lists or Tuples?\n\nIf you need to iterate over the values use a list.\n\nWhen dealing with **large** lists or tuples:\n\n- `Updating` a `list` (adding or removing elements) is **fast**\n- `Updating` a `tuple` is **slow**\n\n- `Reading` a `list` (getting its length or selecting an element) is **slow**\n- `Reading` a `tuple` is **fast**\n\n\u003e source: http://stackoverflow.com/questions/31192923/lists-vs-tuples-what-to-use-and-when\n\n## Functions and Modules\n\n### Anonymous functions\n\nAnonymous functions start with `fn` and end with `end`.\n\n```elixir\niex\u003e add = fn a, b -\u003e a + b end\n\niex\u003e add.(1, 2)\n3\n```\n\nNote a dot `.` between the variable `add` and parenthesis is required\nto invoke an anonymous function.\n\nIn Elixir, functions are `first class citizens` meaning that they can\nbe passed as arguments to other functions the same way integers and strings can.\n\n```elixir\niex\u003e is_function(add)\ntrue\n```\n\nThis uses the inbuilt function `is_function` which checks to see if\nthe parameter passed is a function and returns a bool.\n\nAnonymous functions are [closures](https://developer.mozilla.org/en/docs/Web/JavaScript/Closures) (_named_ functions are not)\nand as such they can access variables\nthat are in scope when the function is defined.\nYou can define a new anonymous function that uses the `add`\nanonymous function we have previously defined:\n\n```elixir\niex\u003e double = fn a -\u003e add.(a, a) end\n\niex\u003e double.(5)\n10\n```\n\nThese functions can be useful but will no longer be available to you.\nIf you want to make something more permanent then you can create a `module`.\n\n### Modules\n\nWith modules you're able to group several functions together.\nMost of the time it is convenient to write modules into files\nso they can be compiled and reused.\n\nGet started by creating a file named `math.ex`,\nopen it in your text editor and add the following code\n\n```elixir\ndefmodule Math do\n  def sum(a, b) do\n    a + b\n  end\nend\n```\n\nIn order to create your own modules in Elixir, use the `defmodule` [macro](https://www.google.co.uk/webhp?sourceid=chrome-instant\u0026ion=1\u0026espv=2\u0026ie=UTF-8#q=what+is+a+macro\u0026*),\nthen use the `def` macro to define functions in that module.\nSo in this case the module is `Math` and the function is `sum`.\n\nOnce this is saved the file can be compiled by typing `elixirc`\ninto the terminal followed by the file name.\n\n```\n$ elixirc math.ex\n```\n\nThis will generate a file named `Elixir.Math.beam` containing the bytecode\nfor the defined module. If we start `iex` again, our module definition\nwill be available (provided that `iex` is started\nin the same directory the bytecode file is in):\n\n```elixir\niex\u003e Math.sum(1, 2)\n3\n```\n\n## Create Your First `Elixir` Project\n\nTo get started\nwith your first **`Elixir`** project\nyou need to make use of the\n[**`Mix`**](https://hexdocs.pm/mix/Mix.html)\nbuild tool that comes with **`Elixir`**.\nMix allows you to do a number of things including:\n\n- Create projects\n- Compile projects\n- Run tasks\n  - Testing\n  - Generate documentation\n- Manage dependencies\n\nTo generate a new project follow these steps:\n\n### Initialise\n\nInitialise a project by typing the following command in your terminal,\nreplacing [project_name] with the name of your project:\n\n```sh\nmix new [project_name]\n```\n\ne.g:\n\n```sh\nmix new animals\n```\n\nWe have chosen to call our project 'animals'\n\nThis will create a new folder\nwith the given name of your project\nand should also print something\nthat looks like this to the command line:\n\n```bash\n* creating README.md\n* creating .formatter.exs\n* creating .gitignore\n* creating mix.exs\n* creating lib\n* creating lib/animals.ex\n* creating test\n* creating test/test_helper.exs\n* creating test/animals_test.exs\n\nYour Mix project was created successfully.\nYou can use \"mix\" to compile it, test it, and more:\n\n    cd animals\n    mix test\n\nRun \"mix help\" for more commands.\n```\n\nNavigate to your newly created directory:\n\n```bash\n\u003e cd animals\n```\n\nOpen the directory in your text editor. You will be able to see that **`Elixir`** has\ngenerated a few files for us that are specific to our project:\n\n- `lib/animals.ex`\n- `test/animals_test.ex`\n\n### Edit `animals.ex`\n\nOpen up the `animals.ex` file\nin the lib directory.\nYou should already see some\n`hello-world` boilerplate like this:\n\n```elixir\ndefmodule Animals do\n  @moduledoc \"\"\"\n  Documentation for Animals.\n  \"\"\"\n\n  @doc \"\"\"\n  Hello world.\n\n  ## Examples\n\n      iex\u003e Animals.hello()\n      :world\n\n  \"\"\"\n  def hello do\n    :world\n  end\nend\n```\n\n**`Elixir`** has created a module\nwith the name of your project\nalong with a function\nthat prints out a `:world` atom when called.\nIt's also added boilerplate for\nmodule and function documentation - the first part of the file.\n(_we will go into more detail about documentation later_)\n\n### Run the Code\n\nLet's test out the boilerplate code.\nIn your project directory type the following command:\n\n```sh\n\u003e iex -S mix\n```\n\nWhat this means is:\n\"Start the **`Elixir` REPL**\nand compile with the context of my current project\".\nThis allows you to access modules and\nfunctions created within the file tree.  \nCall the `hello-world` function given to us by **`Elixir`**.\nIt should print out the\n`:world` atom to the command line:\n\n```bash\n\u003e Animals.hello\n# :world\n```\n\n### Define Functions\n\nLet's start to create our own methods in the `Animals` module.\nReplace the `hello-world` function with the following:\n\n```elixir\n@doc \"\"\"\ncreate_zoo returns a list of zoo animals\n\n## Examples\n\n    iex\u003e Animals.create_zoo\n    [\"lion\", \"tiger\", \"gorilla\", \"elephant\", \"monkey\", \"giraffe\"]\n\n\"\"\"\ndef create_zoo do\n  [\"lion\", \"tiger\", \"gorilla\", \"elephant\", \"monkey\", \"giraffe\"]\nend\n```\n\nTo run our new code we will first have to recompile our `iex`.\nThis can be done by typing:\n\n```sh\n\u003e recompile()\n```\n\nNow we will have access to the `create_zoo` method. Try it out in the command line:\n\n```sh\n\u003e Animals.create_zoo\n# [\"lion\", \"tiger\", \"gorilla\", \"elephant\", \"monkey\", \"giraffe\"]\n```\n\n### Extend Functions\n\nLet's _extend_ the `Animals` module.\nImaging you're visiting the zoo\nbut you can't decide which order to view the animals.\nWe can create a `randomise` function\nbefore the final `end` that takes a list of animals\nand returns a new list with a random order:\n\n```elixir\n@doc \"\"\"\nrandomise takes a list of zoo animals and returns a new randomised list with\nthe same elements as the first.\n\n## Examples\n\n    iex\u003e zoo = Animals.create_zoo\n    iex\u003e Animals.randomise(zoo)\n    [\"monkey\", \"tiger\", \"elephant\", \"gorilla\", \"giraffe\", \"lion\"]\n\n\"\"\"\ndef randomise(zoo) do\n  Enum.shuffle(zoo)\nend\n```\n\n\u003e **Note**: we are making use\n\u003e of a pre-built module called `Enum`\n\u003e which has a list of functions\n\u003e that you can use on enumerables such as lists.\n\u003e Documentation available at:\n\u003e [hexdocs.pm/elixir/Enum.html](https://hexdocs.pm/elixir/Enum.html)\n\n### Add More Functions!\n\nLet's add another function\nto the `Animals` module.\nWe want to find out\nif our zoo contains an animal:\n\n```elixir\n@doc \"\"\"\ncontains? takes a list of zoo animals and a single animal and returns a boolean\nas to whether or not the list contains the given animal.\n\n## Examples\n\n    iex\u003e zoo = Animals.create_zoo\n    iex\u003e Animals.contains?(zoo, \"gorilla\")\n    true\n\"\"\"\ndef contains?(zoo, animal) do\n  Enum.member?(zoo, animal)\nend\n```\n\n**NOTE:** It's convention when writing a function that returns a boolean to add a question\nmark after the name of the method.\n\n### Pattern Matching _Example_\n\nCreate a function\nthat takes a list of animals\nand the number of animals\nthat you'd like to see\nand returns a list of animals:\n\n```elixir\n@doc \"\"\"\nsee_animals takes a list of zoo animals and the number of animals that\nyou want to see and then returns a list\n\n## Examples\n\n    iex\u003e zoo = Animals.create_zoo\n    iex\u003e Animals.see_animals(zoo, 2)\n    [\"monkey\", \"giraffe\"]\n\"\"\"\ndef see_animals(zoo, count) do\n  # Enum.split returns a tuple so we have to pattern match on the result\n  # to get the value we want out\n  {_seen, to_see} = Enum.split(zoo, -count)\n  to_see\nend\n```\n\n### Save Data to File\n\nWrite a function\nthat will\nsave our list of animals to a file:\n\n```elixir\n@doc \"\"\"\nsave takes a list of zoo animals and a filename and saves the list to that file\n\n## Examples\n\n    iex\u003e zoo = Animals.create_zoo\n    iex\u003e Animals.save(zoo, \"my_animals\")\n    :ok\n\"\"\"\ndef save(zoo, filename) do\n  # erlang is converting the zoo list to something that can be written to the\n  # file system\n  binary = :erlang.term_to_binary(zoo)\n  File.write(filename, binary)\nend\n```\n\nIn your command line,\nrun the following after recompiling:\n\n```sh\n\u003e zoo = Animals.create_zoo\n\u003e Animals.save(zoo, \"my_animals\")\n```\n\nThis will create a new file\nin your file tree with the name of the file that\nyou specified in the function.\nIt will contain some odd characters:\n\n�l\\\\\u0026#0;\u0026#0;\u0026#0;\u0026#6;m\u0026#0;\u0026#0;\u0026#0;\u0026#4;lionm\u0026#0;\u0026#0;\u0026#0;\u0026#5;tigerm\u0026#0;\u0026#0;\u0026#0;\u0026#7;gorillam\u0026#0;\u0026#0;\u0026#0;\u0026#8;elephantm\u0026#0;\u0026#0;\u0026#0;\u0026#6;monkeym\u0026#0;\u0026#0;\u0026#0;\u0026#7;giraffej\n\n### Retrieve Data from File\n\nWrite a function\nthat will fetch data from the file:\n\n```elixir\n@doc \"\"\"\nload takes filename and returns a list of animals if the file exists\n\n## Examples\n\n    iex\u003e Animals.load(\"my_animals\")\n    [\"lion\", \"tiger\", \"gorilla\", \"elephant\", \"monkey\", \"giraffe\"]\n    iex\u003e Animals.load(\"aglkjhdfg\")\n    \"File does not exist\"\n\n\"\"\"\ndef load(filename) do\n  # here we are running a case expression on the result of File.read(filename)\n  # if we receive an :ok then we want to return the list\n  # if we receive an error then we want to give the user an error-friendly message\n  case File.read(filename) do\n    {:ok, binary} -\u003e :erlang.binary_to_term(binary)\n    {:error, _reason} -\u003e \"File does not exist\"\n  end\nend\n```\n\nThe\n[`case` expression](https://elixir-lang.org/getting-started/case-cond-and-if.html)\nallows us to pattern match\nagainst various options and react accordingly.\n\n#### Pipe Operator\n\nWhat if we wanted to call some of our functions in succession to another? Let's create a function that creates a zoo, randomises it and then returns a selected number of animals to go and see:\n\n```elixir\n@doc \"\"\"\nselection takes a number, creates a zoo, randomises it and then returns a list\nof animals of length selected\n\n## Examples\n\n    iex\u003e Animals.selection(2)\n    [\"gorilla\", \"giraffe\"]\n\n\"\"\"\ndef selection(number_of_animals) do\n  # We are using the pipe operator here. It takes the value returned from\n  # the expression and passes it down as the first argument in the expression\n  # below. see_animals takes two arguments but only one needs to be specified\n  # as the first is provided by the pipe operator\n  Animals.create_zoo()\n  |\u003e Animals.randomise()\n  |\u003e Animals.see_animals(number_of_animals)\nend\n```\n\nNow that we have the functionality for our module,\nlet's take a look at the documentation\nthat we have written\nand how we can maximise its use.\n\n## Documentation\n\nWhen we created a new project with mix, it created a file for us called `mix.exs`\nwhich is referred to as the 'MixFile'. This file holds information about our\nproject and its dependencies.\n\nAt the bottom of the file it gives us a function called `deps` which manages all\nof the dependencies in our project. To install a third party package we need to\nmanually write it in the deps function (_accepts a tuple of the package name and\nthe version_) and then install it in the command line. Let's install `ex_doc` as\nan example:\n\nAdd the following to the deps function in your `mix.exs` file:\n\n```elixir\ndefp deps do\n  [\n    {:ex_doc, \"~\u003e 0.21\"}\n  ]\nend\n```\n\nThen in the command line quit your `iex` shell and enter the following to install\nthe `ex_docs` dependency:\n\n```sh\n\u003e mix deps.get\n```\n\nYou might receive an error saying:\n\n```sh\nCould not find Hex, which is needed to build dependency :ex_doc\nShall I install Hex? (if running non-interactively,\nuse: \"mix local.hex --force\") [Yn]\n```\n\nIf you do then just enter `y`\nand then press enter.\nThis will install the\ndependencies that you need.\n\nOnce `ex_docs` has been installed,\nrun the following command to generate\ndocumentation (_make sure you're not in `iex`_):\n\n```sh\n\u003e mix docs\n```\n\nThis will generate documentation\nthat can be viewed\nif you copy the file path\nof the `index.html` file\nwithin the newly created `doc` folder\nand then paste it in your browser.\nIf you have added documentation\nto your module and functions\nas per the examples above,\nyou should see something like the following:\n\n![api](https://cloud.githubusercontent.com/assets/12450298/22835012/260b07f4-efaf-11e6-9704-690c6c245c37.png)\n\nIt looks exactly like the format\nof the official **`Elixir`** docs\nbecause they used the same tool to create theirs.\nHere is what the method documentation\nshould look like if you click on `Animals`:\n\n![doc](https://cloud.githubusercontent.com/assets/12450298/22835092/763c66c8-efaf-11e6-8428-3c2650c64eb8.png)\n\n![functions](https://cloud.githubusercontent.com/assets/12450298/22835113/8607cd72-efaf-11e6-9850-1c7885416b2e.png)\n\nThis is an incredibly powerful tool\nthat comes 'baked in' with elixir.\nIt means that other developers\nwho are joining the project\ncan be brought up to speed incredibly quickly!\n\n## Testing\n\nWhen you generate a project with **`Elixir`** it automatically gives you a number of\nfiles and directories. One of these directories is called `test` and it holds two\nfiles that should have names like:\n\n- `[project_name]_test.exs`\n- `test_helper.exs`\n\nOur first file was called `animals_test.exs` and it contained some boilerplate that\nlooks like:\n\n```elixir\ndefmodule AnimalsTest do\n  use ExUnit.Case\n  doctest Animals\n\n  test \"greets the world\" do\n    assert Animals.hello() == :world\n  end\nend\n```\n\n**NOTE:** It automatically includes a line called `doctest Animals`. What this means\nis that it can run tests from the examples in the documentation that you write for\nyour functions\n\nTo run the tests enter the following in your terminal:\n`mix test`  \nIt should print out whether the tests pass or fail.\n\nLet's add some tests of our own. Firstly let's write a test for the `Animals.randomise`\nfunction. The reason why we wouldn't want to write a doctest for this is because\nthe output value changes everytime you call it. Here's how we would write a test\nfor that type of function:\n\nIn the `animals_test.exs` file, remove the boilerplate \"greets the world\" test and then\nadd this to test that the order of the animals in `zoo` changes (is randomised):\n\n```elixir\ntest \"randomise\" do\n  zoo = Animals.create_zoo\n  assert zoo != Animals.randomise(zoo)\nend\n```\n\n**NOTE: You do not need to install and require any external testing frameworks**.\nIt all comes with the **`Elixir`** package. Simply write `test` followed by a string\nrepresenting what you are trying to test and then write your assertion.\n\nThe test above isn't completely air-tight. **`Elixir`** provides you with assertions that\ncan help deal with things like this. The test could be re-written like so:\n\n```elixir\ntest \"randomise\" do\n  zoo = Animals.create_zoo\n  refute zoo == Animals.randomise(zoo)\nend\n```\n\nThis is basically saying \"prove to be false that zoo is equal to Animals.randomise(zoo)\"\n\nIf you want to learn about code coverage then check out the following\ntutorial,\nhttps://github.com/dwyl/learn-elixir/tree/master/codecov_example\n\n## Formatting\n\nIn **`Elixir`** version 1.6 the `mix format` task was introduced.\nsee: https://github.com/elixir-lang/elixir/issues/6643\n\n`mix format` is a _built-in_ way to format your **`Elixir`** code\naccording to the community-agreed consistent style.\nThis means _all_ code will look consistent across projects\n(_personal, \"work\" \u0026 hex.pm packages_)\nwhich makes learning faster and maintainability easier!\nAt present, using the formatter is _optional_,\nhowever _most_ **`Elixir`** projects have adopted it.\n\nTo _use_ the mix task in your project,\nyou can either check files _individually_, e.g:\n\n```sh\nmix format path/to/file.ex\n```\n\nOr you can define a _pattern_ for types of files\nyou want to check the format of:\n\n```sh\nmix format \"lib/**/*.{ex,exs}\"\n```\n\nwill check all the `.ex` and `.exs` files in the `lib/` directory.\n\nHaving to type this pattern each time\nyou want to check the files is _tedious_.\nThankfully, **`Elixir`** has you covered.\n\nIn the root of your **`Elixir`** project, you will find a `.formatter.exs`\nconfig file with the following code:\n\n```elixir\n# Used by \"mix format\"\n[\n  inputs: [\"{mix,.formatter}.exs\", \"{config,lib,test}/**/*.{ex,exs}\"]\n]\n```\n\nThis means that if you run `mix format` it will check the `mix.exs` file\nand _all_ `.ex` and `.exs` files in the `config`, `lib/` and `test` directories.\n\nThis is the most common pattern for running mix format.\nUnless you have a _reason_ to \"deviate\" from it, it's a good practice to keep it as it is.\n\nSimply run:\n\n```sh\nmix format\n```\n\nAnd your code will now follow Elixir's formatting guidelines.\n\nWe recommend installing a plugin in your Text Editor to auto-format:\n\n- **Atom** Text Editor Auto-formatter:\n  https://atom.io/packages/atom-elixir-formatter\n- Vim **`Elixir`** Formatter: https://github.com/mhinz/vim-mix-format\n- VSCode:\n  https://marketplace.visualstudio.com/items?itemName=sammkj.vscode-elixir-formatter\n\n- Read the `mix/tasks/format.ex` source to _understand_ how it works:\n  https://github.com/elixir-lang/elixir/blob/master/lib/mix/lib/mix/tasks/format.ex\n- https://hashrocket.com/blog/posts/format-your-elixir-code-now\n- https://devonestes.herokuapp.com/everything-you-need-to-know-about-elixirs-new-formatter\n\n## Publishing\n\nTo publish your **`Elixir`** package to [Hex.pm](https://hex.pm/):\n\n- Check the version in `mix.exs` is up to date and that it follows the\n  [semantic versioning format](https://semver.org/):\n\n  \u003e MAJOR.MINOR.PATCH where\n\n        MAJOR version when you make incompatible API changes\n        MINOR version when you add functionality in a backwards-compatible manner\n        PATCH version when you make backwards-compatible bug fixes\n\n- Check that the main properties of the project are defined in `mix.exs`\n\n  - name: The name of the package\n  - description: A short description of the package\n  - licenses: The names of the licenses of the package\n  - NB. dwyl's `cid` repo contains an [example of a more advanced\n    `mix.exs` file](https://github.com/dwyl/cid/blob/master/mix.exs) where\n    you can see this in action\n\n- Create a [Hex.pm](https://hex.pm/) account\n  if you do not have one already.\n\n- Make sure that [ex_doc](https://hex.pm/packages/ex_doc)\n  is added as a dependency in you project\n\n```elixir\ndefp deps do\n[\n  {:ex_doc, \"~\u003e 0.21\", only: :dev}\n]\nend\n```\n\nWhen publishing a package, the documentation will be automatically generated.\nSo if the dependency `ex_doc` is not declared, the package won't be able to be published\n\n- Run `mix hex.publish`\n  and if all the information are correct reply `Y`\n\nIf you have not logged into your Hex.pm account\nin your command line before running the above command,\nyou will be met with the following...\n\n```sh\nNo authenticated user found. Do you want to authenticate now? [Yn]\n```\n\nYou will need to reply `Y`\nand follow the on-screen instructions\nto enter your Hex.pm username and password.\n\nAfter you have been authenticated,\nHex will ask you for a local password that\napplies only to the machine you are using for security purposes.\n\nCreate a password for this\nand follow the onscreen instructions to enter it.\n\n- Now that your package is published you can create a new git tag with the name of the version:\n  - `git tag -a 0.1.0 -m \"0.1.0 release\"`\n  - `git push --tags`\n\n### Congratulations!\n\nThat's it, you've generated, formatted\nand published your first **`Elixir`** project :tada:\n\n### Want _More_?\n\nIf you want a more detailed example\nof publishing a real-world package\nand re-using it in a real-world project,\nsee:\n[**`code-reuse-hexpm.md`**](https://github.com/dwyl/learn-elixir/blob/main/code-reuse-hexpm.md)\n\n\u003chr/\u003e\n\n## Data Structures\n\n### Maps\n\nMaps are very similar to `Object` literals in `JavaScript`.\nThey have almost the same\nsyntax except for a `%` symbol.\nThey look like this:\n\n```elixir\nanimal = %{\n  name: \"Rex\",\n  type: \"dog\",\n  legs: 4\n}\n```\n\nValues can be accessed in a couple of ways.\nThe first is by dot notation just\nlike `JavaScript`:\n\n```elixir\nname = animal.name\n# Rex\n```\n\nThe second way values\ncan be accessed is by pattern matching.\nLet's say we wanted\nto assign values to variables\nfor each of the key-value pairs in the map.\nWe would write something that looks like this:\n\n```elixir\niex\u003e %{\n  name: name,\n  type: type,\n  legs: legs\n} = animal\n# we now have access to the values by typing the variable names\niex\u003e name\n# \"Rex\"\niex\u003e type\n# \"dog\"\niex\u003e legs\n# 4\n```\n\n#### Updating a value inside a map\n\nDue to the immutability of **`Elixir`**,\nyou cannot update a map\nusing dot notation\nfor example:\n\n```elixir\niex\u003e animal = %{\n  name: \"Rex\",\n  type: \"dog\",\n  legs: 4\n}\niex\u003e animal.name = \"Max\" # this cannot be done!\n```\n\nIn **`Elixir`** we can only create new data structures as opposed to manipulating existing\nones. So when we _update_ a map, we are creating a new map with our new values.\nThis can be done in a couple of ways:\n\n- Function\n- Syntax\n\n1. Using a function  \n   We can update a map using `Map.put(map, key, value)`.\n   This takes the map you want to update\n   followed by the key we want to reassign\n   and lastly the value that we want\n   to reassign to the key:\n\n```elixir\niex\u003e updatedAnimal = Map.put(animal, :name, \"Max\")\niex\u003e updatedAnimal\n# %{legs: 4, name: \"Max\", type: \"dog\"}\n```\n\n2. Using syntax  \n   We can use a special syntax for updating a map in Elixir.\n   It looks like this:\n\n```elixir\niex\u003e %{animals | name: \"Max\"}\n# %{legs: 4, name: \"Max\", type: \"dog\"}\n```\n\n\u003e **NOTE:** Unlike the function method above,\n\u003e this syntax can only be used to UPDATE\n\u003e a current key-value pair inside the map,\n\u003e it cannot add a new key value pair.\n\n## Processes\n\nWhen looking into **`Elixir`** you may have heard about its\n[processes](https://elixir-lang.org/getting-started/processes.html)\nand its support for concurrency.\nIn fact we even mention processes\nas one of the key advantages.\nIf you're anything like us,\nyou're probably wondering\nwhat this actually means for you and your code.\nThis section aims to help you\nunderstand what they are\nand how they can help improve\nyour **`Elixir`** projects.\n\n**`Elixir-lang`** describes processes as:\n\n\u003e In **`Elixir`**, all code runs inside processes.\n\u003e Processes are isolated from each other,\n\u003e run concurrent to one another\n\u003e and communicate via message passing.\n\u003e Processes are not only the basis\n\u003e for concurrency in **`Elixir`**,\n\u003e but they also provide the means\n\u003e for building distributed and fault-tolerant programs.\n\nNow that we have a definition,\nlet's start by spawning our first process.\n\n### Spawning a process\n\nCreate a file called `math.exs`\nand insert the following code:\n\n```elixir\ndefmodule Math do\n  def add(a, b) do\n    a + b\n    |\u003e IO.inspect()\n  end\nend\n```\n\nNow head over to your terminal\nand enter the following, `iex math.exs`.\nThis will load your `Math` module\ninto your `iex` session.\nNow in `iex` type:\n\n```elixir\nspawn(Math, :add, [1,2])\n```\n\nYou will see something similar to:\n\n```elixir\n3\n#PID\u003c0.118.0\u003e\n```\n\nThis is your log\nfollowed by a `process identifier`, PID for short.\nA PID is a unique id for a process.\nIt could be unique among all processes in the world,\nbut here it's just unique for your application.\n\nSo what just happened here.\nWe called the\n[`spawn/`3](https://hexdocs.pm/elixir/Kernel.html#spawn/3)\nfunction\nand passed it 3 arguments.\nThe module name,\nthe function name (as an atom),\nand a list of the arguments\nthat we want to give to our function.\nThis one line of code spawned\na process for us 🎉 🥳\n\nNormally we would not see the result\nof the function (3 in this case).\nThe only reason we have\nis because of the `IO.inspect` in the add function.\nIf we removed this the only log we would have is the PID itself.\n\nThis might make you wonder,\nwhat good is spawning a process if I can't get\naccess to the data it returns.\nThis is where messages come in.\n\n### Sending messages between processes\n\nLet's start by exiting `iex`\nand removing the the `IO.inspect` line\nfrom our code.\nNow that that is done\nlet's get our add function\nto send its result in a message.\n\nUpdate your file to the following:\n\n```elixir\ndefmodule Math do\n  def add(a, b) do\n    receive do\n      senders_pid -\u003e\n        send(senders_pid, a + b)\n    end\n  end\n\n  def double(n) do\n    spawn(Math, :add, [n,n])\n    |\u003e send(self())\n\n    receive do\n      doubled -\u003e\n        doubled\n    end\n  end\nend\n```\n\nLet's go through all the new code.\nWe have added a new function called double. This function spawns the `Math.add/2`\nfunction (as we did in the `iex` shell in the previous example). Remember the\nspawn function returned a PID. We use this PID on the next line with\n`|\u003e send(self())`. [send/2](https://hexdocs.pm/elixir/Kernel.html#send/2) takes\ntwo arguments, a destination and a message. For us the destination is the PID\ncreated by the `spawn` function on the line above. The message is\n[`self/0`](https://hexdocs.pm/elixir/Kernel.html#self/0)\nwhich returns the PID\nof the calling process (the PID of double).\n\nWe then call\n[`receive/1`](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#receive/1)\nwhich checks if there is a message matching the clauses in the current process.\nIt works very similarly to a `case` statement.\nOur `message` is simple and just\nreturns whatever the message was.\n\nWe have also updated our `add/2` function\nso that it also contains a `receive` and a `send`.\nThis `receive`, receives the PID of the sender.\nOnce it has that message\nit calls the send function\nto send a message back to the sender.\nThe message it sends is `a+b`.\n\nThis will trigger the receive block in our double function. As mentioned\nabove, it simply returns the message it receives which is the answer from add.\n\nLet's test this code in `iex`. Change to your terminal and type\n`iex math.exs` again. In `iex` type `Math.double(5)`.\n\nYou should see\n\n```elixir\n10\n```\n\nVERY COOL.\nWe just spawned a process\nwhich did a task for us\nand returned the data.\n\n### Concurrency\n\nNow that we can create processes that can send messages to each other, let's see\nif we can use them for something a little more intensive than doubling an\ninteger.\n\nIn this example we will aim to see exactly how concurrency can be used to\nspeed up a function (and in turn, hopefully a project).\n\nWe are going to do this by solving factorials using two different approaches.\nOne will solve them on a single process and the other will solve them using\nmultiple processes.\n\n(A factorial is the product of an integer and all the integers below it;\ne.g. `factorial(4) (4!)` is equal to `1 * 2 * 3 * 4` or `24`.)\n\nCreate a new file called `factorial.exs` with the following code:\n\n```elixir\ndefmodule Factorial do\n  def spawn(n) do\n    1..n\n    |\u003e Enum.chunk_every(4)\n    |\u003e Enum.map(fn(list) -\u003e\n      spawn(Factorial, :_spawn_function, [list])\n      |\u003e send(self())\n\n      receive do\n        n -\u003e n\n      end\n    end)\n    |\u003e calc_product()\n  end\n\n  def _spawn_function(list) do\n    receive do\n      sender -\u003e\n        product = calc_product(list)\n        send(sender, product)\n    end\n  end\n\n  # used on the single process\n  def calc_product(n) when is_integer(n) do\n    Enum.reduce(1..n, 1, \u0026(\u00261 * \u00262))\n  end\n\n  # used with multiple processes\n  def calc_product(list) do\n    Enum.reduce(list, 1, \u0026(\u00261 * \u00262))\n  end\nend\n```\n\nThe `\u0026` symbol is called the\n[capture operator](https://hexdocs.pm/elixir/Function.html#module-the-capture-operator),\nwhich can be used to quickly generate anonymous functions that expect at least one argument.\nThe arguments can be accessed inside the _capture operator_ `\u0026()` with `\u0026X`, where\n`X` refers to the input number of the argument.\n\nThere is no difference between\n\n```elixir\nadd_capture = \u0026(\u00261 + \u00262)\nadd_fn = fn a, b -\u003e a + b end\n```\n\nBefore we go any further let's take a quick look at the `calc_product` function.\nYou will see that there are 2 definitions for this function. One which takes a\nlist and another which takes an integer and turns it into a range. Other than\nthis, the functions work in exactly the same way. They both call reduce on an\nenumerable and multiply the current value with the accumulator.\n\n(The reason both work the same way is so that we could see the effect multiple\nprocesses running concurrently have on how long it takes for us to get the\nresults of our factorial. I didn't want differences in a functions approach\nto be the reason for changes in time. Also these factorial functions are not\nperfect and do not need to be. That is not what we are testing here.)\n\nNow we can test if our `calc_product` function works as expected. In your `iex`\nshell load the `Factorial` module with `c(\"factorial.exs\")`. Now type\n`Factorial.calc_product(5)`. If you get an output of `120` then everything is\nworking as expected and you just solved a factorial on a single process.\n\nThis works well on a smaller scale but what if we need/want to work out\n`factorial(100_000)`. If we use this approach it will take quite some time\nbefore it we get the answer returned (something we will log a little later).\nThe reason for this is because this massive sum is being run on a single\nprocess.\n\nThis is where spawning multiple processes comes in. By spawning multiple\nprocesses, instead of giving all of the work to a single process, we can share\nthe load between any number of processes. This way each process is only handling\na portion of the work and we should be able to get our solution faster.\n\nThis sounds good in theory but let's see if we can put it into practice.\n\nFirst, let's look through the `spawn` function and try to work out what it is\ndoing exactly.\n\nThe function starts by converting an integer into a range which it then\n'[chunks](https://hexdocs.pm/elixir/Enum.html#chunk_every/4)' into a list of\nlists with 4 elements.\nThe number 4 itself is not important, it could have been 5, 10, or 1000. What is\nimportant about it, is that it influences the number of processes we will be spawning.\nThe larger the size of the 'chunks' the fewer processes are spawned.\n\nNext, we map over the 'chunked' range and call the spawn function. This\nspawns a new process for each chunked list running the `_spawn_function/1`.\nAfterwards, the process running the `spawn/1` function sends the newly\ncreated process a message and waits for a response message.\n\nThe `_spawn_function` function is pretty simple. It uses the exact same pattern\nwe used in our `add` function earlier. It receives a message with the senders\nPID and then sends a message back to them. The message it sends back is the\nresult of the `calc_product` function.\n\nOnce each process in the map function has received a result, we then call the\n`calc_product` once more to turn the list of results from map into a single integer,\nthe factorial.\nIn total the `spawn/1` function will end up calling\n`calc_product` for a list with `n` elements:\n`n % 4 + 1` if `n % 4 == 0` else `n % 4 + 2` times.\n\nRemember, we split the original list into lists of 4 elements.\nThe only exception is the last chunk, which may contain fewer elements:\n\n`[1, 2, 3, 4, 5] -\u003e [[1, 2, 3, 4], [5]]`\n\nFor each chunked list we call `calc_product` and to calculate the final result,\nthe factorial, once.\n\nNow that we have been through the code the only things left are to run the code\nand to time the code.\n\nTo time the execution of our code,\nadd the following to your `factorial.exs` file:\n\n```elixir\n  # just a helper function used to time the other functions\n  def run(f_name, args) do\n    :timer.tc(Factorial, f_name, args)\n    |\u003e elem(0) # only displays the time as I didn't want to log numbers that could have thousands of digits\n    |\u003e IO.inspect(label: \"-----\u003e\")\n  end\n```\n\nYou can feel free to comment out the `|\u003e elem(0)` line. I left it in because we\nare about to have a MASSIVE number log in our terminal and we don't really need\nto see it.\n\nNow we have all the code we will need. All that's left is to call the code.\n\nLet's go back to our `iex` shell and retype the `c(\"factorial.exs\")` command.\nNow type the following `Factorial.run(:calc_product, [10_000])`. You should get\na log of the number of milliseconds it took to run the function.\n\nNext type `Factorial.run(:spawn, [10_000])`. Compare to two logs. You should\nhave something that looks like this...\n\n![image](https://user-images.githubusercontent.com/15571853/48916327-aadf1400-ee79-11e8-87be-185f8171d478.png).\n\nFeel free to try this test again with even larger numbers (if you don't mind the\nwait of course).\n\n## tl;dr\n\n\u003e **_Note_**: this is _definitely **not**_ a \"_reason_\" to switch programming\n\u003e languages, but _one_ of our (_totally unscientific_) reasons for deciding\n\u003e to _investigate_ other options for programming languages was the fact\n\u003e that JavaScript (_with the introduction of ES2015_) now has\n\u003e **_Six Ways to Declare a Function_**:\n\u003e https://rainsoft.io/6-ways-to-declare-javascript-functions/\n\u003e which means that there is _ambiguity_ and \"_debate_\" as to which is\n\u003e \"_best practice_\", Go, **`Elixir`** and Rust don't suffer from this problem.\n\u003e Sure there are \"_anonymous_\" functions in Elixir\n\u003e (_required for functional programming_!) but there are still only **_Two Ways_**\n\u003e to define a `function` (_and both have specific use-cases_),\n\u003e which is _way_ easier to explain to a _beginner_ than the JS approach.\n\u003e see:\n\u003e http://stackoverflow.com/questions/18011784/why-are-there-two-kinds-of-functions-in-elixir\n\n## Further resources:\n\n- [Crash Course in Elixir](http://elixir-lang.org/crash-course.html)\n- [Elixir School](https://elixirschool.com/),\n  which is available translated at least partially in over **20 languages**\n  and functions as a great succinct guide to core concepts.\n- [30 Days of Elixir](https://github.com/seven1m/30-days-of-elixir)\n  is a walk through the **`Elixir`** language in 30 exercises.\n- [Learn **`Elixir`** - List of Curated Resources](https://hackr.io/tutorials/learn-elixir)\n- [Explanation video of **Pattern Matching** in Elixir](http://worldwide.chat/)\n- Sign up to: https://elixirweekly.net/ for regular (_relevant_) updates!\n- List of more [useful resources and sample apps](https://github.com/h4cc/awesome-elixir)\n- If you want to know what's _next_ it's worth check out\n  [What's Ahead for Elixir?](https://youtu.be/A60nxws_iVs) (53 mins)\n  by **José Valim** (the creator of Elixir)\n- _Interview_ with **José Valim** (the creator of Elixir) on _why_ he made it!\n  https://www.sitepoint.com/an-interview-with-elixir-creator-jose-valim/\n- What was \"_wrong_\" with just writing directly in Erlang? read:\n  http://www.unlimitednovelty.com/2011/07/trouble-with-erlang-or-erlang-is-ghetto.html\n- While **`Elixir`** by _itself_ is pretty _amazing_,\n  where the language really shines is in the **Phoenix Web Framework**!!\n  So once you know the basics of the language\n  [Learn `Phoenix` Web Development](https://github.com/dwyl/learn-phoenix-web-development).\n","funding_links":[],"categories":["Elixir","beginner-friendly","Prerequisites: What you Need _Before_ You Start 📝"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdwyl%2Flearn-elixir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdwyl%2Flearn-elixir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdwyl%2Flearn-elixir/lists"}