Run this notebook

Use Livebook to open this notebook and explore new ideas.

It is easy to get started, on your machine or the cloud.

Click below to open and run it in your Livebook at .

(or change your Livebook location)

# Enum ```elixir Mix.install([ {:jason, "~> 1.4"}, {:kino, "~> 0.9", override: true}, {:youtube, github: "brooklinjazz/youtube"}, {:hidden_cell, github: "brooklinjazz/hidden_cell"}, {:smart_animation, github: "brooklinjazz/smart_animation"}, {:visual, github: "brooklinjazz/visual"} ]) ``` ## Navigation <div style="display: flex; align-items: center; width: 100%; justify-content: space-between; font-size: 1rem; color: #61758a; background-color: #f0f5f9; height: 4rem; padding: 0 1rem; border-radius: 1rem;"> <div style="display: flex;"> <i class="ri-home-fill"></i> <a style="display: flex; color: #61758a; margin-left: 1rem;" href="../start.livemd">Home</a> </div> <div style="display: flex;"> <i class="ri-bug-fill"></i> <a style="display: flex; color: #61758a; margin-left: 1rem;" href="https://github.com/DockYard-Academy/curriculum/issues/new?assignees=&labels=&template=issue.md&title=Enum">Report An Issue</a> </div> <div style="display: flex;"> <i class="ri-arrow-left-fill"></i> <a style="display: flex; color: #61758a; margin-left: 1rem;" href="../reading/ranges.livemd">Ranges</a> </div> <div style="display: flex;"> <a style="display: flex; color: #61758a; margin-right: 1rem;" href="../exercises/fizzbuzz.livemd">FizzBuzz</a> <i class="ri-arrow-right-fill"></i> </div> </div> ## Review Questions Upon completing this lesson, a student should be able to answer the following questions. * When and why might we use enumeration in programming? * How do we transform every element in an enumerable? * How do we remove elements from an enumerable? * How do we use every element in an enumerable to build an acculumator and return a transformed value? ## Overview ### Enumeration Enumeration is the act of looping through elements. Unlike iteration, which you may have encountered in other programming languages, enumeration does not allow you to change (mutate) elements in the original collection. For example, we could enumerate through a list of numbers from one to five, and transform them into a new list of doubled numbers. ```mermaid flowchart subgraph Original direction LR 1 --- 2 --- 3 --- 4 --- 5 end subgraph Transformed direction LR T2[2] --- T4[4] --- T6[6] --- T8[8] --- T10[10] end Original --> Transformed ``` <!-- livebook:{"break_markdown":true} --> ### [Enum](https://hexdocs.pm/elixir/Enum.html) The Elixir [Enum](https://hexdocs.pm/elixir/Enum.html) module contains functions for using enumeration with enumerable data structures. For example, there is the [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) function for applying a transformation function to each element in an enumerable. ```elixir Enum.map([1, 2, 3, 4, 5], fn element -> element * 2 end) ``` ### Enumerable Certain data types in Elixir implement the [Enumerable](https://hexdocs.pm/elixir/Enumerable.html) protocol. That means we can enumerate through elements in these enumerable data types. Most enumerables are collections, but not all of them. For example a range doesn't contain other elements, but it is enumerable. ```elixir Enum.map(1..5, fn element -> element * 2 end) ``` ### Collections Data types that store other elements are often referred to as **collections**. For example, maps, lists, keyword lists, and tuples are all collections. Many collections are enumerable, but not all of them. For example, a tuple is not enumerable. <!-- livebook:{"break_markdown":true} --> ### Map, Filter, And Reduce [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2), [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2), and [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) are the most common functions for enumeration. By understanding these functions and when to use them, you'll be able to solve most enumeration problems. * [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) returns the same number of elements with a transformation applied to each. <!-- livebook:{"break_markdown":true} --> ```mermaid flowchart subgraph map direction LR subgraph input direction LR im1((1)) --> im2((2)) --> im3((3)) end subgraph output direction LR om1[2] --> om2[4] --> om3[6] end input --"Enum.map(1..3, fn el -> el * 2 end)"--> output end ``` ```elixir Enum.map(1..3, fn el -> el * 2 end) ``` * [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2) removes element(s) from an enumerable without transforming them. <!-- livebook:{"break_markdown":true} --> ```mermaid flowchart subgraph map direction LR subgraph input direction LR im1((1)) --> im2((2)) --> im3((3)) end subgraph output direction LR om1((1)) --> om2((2)) end input --"Enum.filter(1..3, fn el -> el <= 2 end)"--> output end ``` ```elixir Enum.filter(1..3, fn el -> el <= 2 end) ``` * [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) uses the elements in an enumerable to build an accumulated value and return a transformed data structure. ```mermaid flowchart subgraph map direction LR subgraph input direction LR im1((1)) --> im2((2)) --> im3((3)) end subgraph output direction LR om1[[6]] end input --"Enum.reduce(1..3, fn el, acc -> acc + el end)"--> output end ``` ```elixir Enum.reduce(1..3, fn el, acc -> acc + el end) ``` ## Scenario Often while programming, you run into problems where you need the ability to do something many many times. For example, let's say you're creating a shopping application. In this application, customers create a shopping list. We'll represent this shopping cart as a list of item costs in pennies. ```elixir shopping_cart = [100, 200, 150, 200] ``` We can create a function that will calculate the after tax cost of an item called `calculate_tax/1`. Lets say that the tax is `5%` so we can multiply our cost by `1.05`. ```elixir calculate_tax = fn cost -> cost * 1.05 end ``` With four items in our shopping list, it's a bit tedius to call the `calculate_tax/1` function on each item. We'd need to bind each item to a variable and call the `calculate_tax/1` function on each item individually to determine the after tax cost of each item. ```elixir [one, two, three, four] = shopping_cart [calculate_tax.(one), calculate_tax.(two), calculate_tax.(three), calculate_tax.(four)] ``` This only works when there are exactly four items. If we want to handle when there is one, two, three, or four items our code gets much more verbose. As you can imagine, this solution is not scalable. ```elixir shopping_cart = [100, 200, 150] case shopping_cart do [] -> [] [one] -> [calculate_tax.(one)] [one, two] -> [calculate_tax.(one), calculate_tax.(two)] [one, two, three] -> [calculate_tax.(one), calculate_tax.(two), calculate_tax.(three)] [one, two, three, four] -> [calculate_tax.(one), calculate_tax.(two), calculate_tax.(three), calculate_tax.(four)] end ``` To solve this problem, we need to apply the `calculate_tax/1` function on every element in the list. Any time we need to repeat a similar action over and over again we can use **enumeration**. Enumeration is the act of looping through a collection and reading its elements for the sake of returning some output. <!-- livebook:{"break_markdown":true} --> ```mermaid flowchart LR Input ---> Enumeration --> Function --> Enumeration Enumeration --> Output ``` <!-- livebook:{"break_markdown":true} --> With enumeration, we can `calculate_tax/1` on any number of items with a single call to [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2). ```elixir shopping_cart = [100, 200, 150] Enum.map(shopping_cart, fn item -> calculate_tax.(item) end) ``` ## The Enum Module Elixir provides the [Enum](https://hexdocs.pm/elixir/Enum.html) to accomplish enumeration. The [Enum](https://hexdocs.pm/elixir/Enum.html) module contains a large amount of useful functions that all work on collection data types such as lists, ranges, maps, and keyword lists. Most enumeration problems can be solved with the following [Enum](https://hexdocs.pm/elixir/Enum.html) functions. * [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) enumerate over every element and create a new collection with a new value. * [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) and [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3). Enumerate over every element into an accumulated value. * [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2) filter out elements from a collection. <!-- livebook:{"break_markdown":true} --> [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) applies the callback function on every element in a collection to build a new list. Each element in the new list will be the return value of the provided callback function. ```elixir Enum.map(1..10, fn element -> element * 2 end) ``` [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2) applies the callback function to every element in the collection and keeps an element when the callback function returns `true`. ```elixir Enum.filter(1..10, fn element -> rem(element, 2) == 0 end) ``` [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) and [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3) applies the callback function to every element in the collection and builds an accumulated value stored between each function call. When complete, it returns the result of the last function call, which is typically the accumulated value ```elixir # 0 Is The Initial Accumulator Value Enum.reduce(1..3, 0, fn element, accumulator -> element + accumulator end) ``` [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) uses the first value in the collection as the initial accumulator. Generally (but not always) [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3) is preferable for the sake of clarity, and we will prefer it for most use cases. ```elixir Enum.reduce(1..3, 5, fn element, accumulator -> element + accumulator end) ``` ```elixir Enum.reduce(1..3, fn element, accumulator -> element + accumulator end) ``` ### Other Handy Functions The [Enum](https://hexdocs.pm/elixir/Enum.html) module also provides other useful functions. Here are a handful of the most used. * [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) check if all elements in a collection match some condition. * [Enum.any?/2](https://hexdocs.pm/elixir/Enum.html#any?/2) check if any elements in a collection match some condition. * [Enum.count/2](https://hexdocs.pm/elixir/Enum.html#count/2) return the number of elements in a collection collection. * [Enum.find/3](https://hexdocs.pm/elixir/Enum.html#find/3) return an element in a collection that matches some condition. * [Enum.random/1](https://hexdocs.pm/elixir/Enum.html#random/1) return a random element in a collection. Anytime we're working with a collection, we should refer to the [Enum](https://hexdocs.pm/elixir/Enum.html) module to see if it has a built-in solution we can use. Alternatively, we can build nearly all functionality using only [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2), [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3), and [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) so consider developing the most familiarity with these three functions. ## Enum.map/2 [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) allows you to enumerate through the collection you provide it as its first argument. It then calls a function that you provide it as its second argument on each element. Finally it returns a new collection with the modified values. ```mermaid flowchart LR A[Collection] --> E[Enum.map] E --> Function Function --> E E --> B[New Collection] ``` Here's an example that doubles all the integers in a list. ```elixir Enum.map([1, 2, 3, 4], fn integer -> integer * 2 end) ``` ```mermaid flowchart LR A["[1, 2, 3, 4]"] --> E[Enum.map] E --> F["fn integer -> integer * 2 end"] F --> E E --> B["[2, 4, 6, 8]"] ``` <!-- livebook:{"break_markdown":true} --> It's useful to be aware that you can use ranges with enumerables to easily enumerate over large ranges without needing to define every element in the list. ```elixir Enum.map(1..100, fn integer -> integer * 2 end) ``` [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) accepts any enumerable, and always returns a list, regardless of the input. **keyword lists** and **maps** will be treated as lists of tuples for the sake of enumeration. ```elixir Enum.map(%{"one" => 1, "two" => 2}, fn element -> element end) ``` ```elixir Enum.map([one: 1, two: 2], fn element -> element end) ``` We can even pattern match on the key and value in the tuple. ```elixir Enum.map(%{"one" => 1, "two" => 2}, fn {_key, value} -> value end) ``` ```elixir Enum.map([one: 1, two: 2], fn {key, _value} -> key end) ``` ### Your Turn Use [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) to convert a list of integers from `1` to `10` to strings. <!-- livebook:{"force_markdown":true} --> ```elixir # Expected Output ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] ``` <details style="background-color: lightgreen; padding: 1rem; margin: 1rem 0;"> <summary>Example Solution</summary> ```elixir Enum.map(1..10, fn integer -> "#{integer}" end) ``` </details> Enter your solution below. ```elixir ``` ## Enum.reduce/2 And Enum.reduce/3 [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) allows you to enumerate over a collection and build up an accumulated value with each enumeration. Unlike [Enum.map/2](https://hexdocs.pm/elixir/Enum.html#map/2) this gives you significantly more control over your output, as the data type of the accumulator and return value do not have to be a list. ```mermaid flowchart LR A[Collection] --> E[Enum.reduce] E -- Accumulator --> Function Function -- Accumulator --> E E --Final Accumulator--> B[Output] ``` <!-- livebook:{"break_markdown":true} --> For example, we can sum all of the numbers in a list by building up an accumulated sum. ```elixir list = [1, 2, 3, 4] Enum.reduce(list, fn integer, accumulator -> integer + accumulator end) ``` The function you provide as the second argument of [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) will be called with the current element, and current accumulator. The first value in the collection will be the initial accumulator value. <!-- livebook:{"attrs":{"source":"frames = [\n \"\nFirst, we define the call the [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) function with a list, and a function.\n```elixir\nEnum.reduce([1, 2, 3, 4], fn integer, accumulator -> integer + accumulator end)\n```\n\",\n \"\nThe first element in the list `1` is the initial accumulator value.\n```elixir\nEnum.reduce([2, 3, 4], fn integer, 1 -> integer + 1 end)\n```\n\",\n \"\nThe function is called on the next element `2`. The next accumulator is 2 + 1\n```elixir\nEnum.reduce([3, 4], fn 2, 1 -> 2 + 1 end)\n```\n\",\n \"\nThe function is called on the next element `3`. The next accumulator is 3 + 3\n```elixir\nEnum.reduce([4], fn 3, 3 -> 3 + 3 end)\n```\n\",\n \"\nThe function is called on the next element `4`. The next accumulator is 4 + 6\n```elixir\nEnum.reduce([], fn 4, 6 -> 4 + 6 end)\n```\n\",\n \"\n4 + 6 equals 10.\n```elixir\nEnum.reduce([], fn 4, 6 -> 10 end)\n```\n\",\n \"\n`10` is the last accumulator value, so [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) returns `10`.\n```elixir\n 10\n```\n\"\n ]\n\nSmartAnimation.new(0..Enum.count(frames) - 1, fn i ->\n Kino.Markdown.new(Enum.at(frames, i))\nend)","title":"Reduce"},"chunks":null,"kind":"Elixir.HiddenCell","livebook_object":"smart_cell"} --> ````elixir frames = [ " First, we define the call the [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) function with a list, and a function. ```elixir Enum.reduce([1, 2, 3, 4], fn integer, accumulator -> integer + accumulator end) ``` ", " The first element in the list `1` is the initial accumulator value. ```elixir Enum.reduce([2, 3, 4], fn integer, 1 -> integer + 1 end) ``` ", " The function is called on the next element `2`. The next accumulator is 2 + 1 ```elixir Enum.reduce([3, 4], fn 2, 1 -> 2 + 1 end) ``` ", " The function is called on the next element `3`. The next accumulator is 3 + 3 ```elixir Enum.reduce([4], fn 3, 3 -> 3 + 3 end) ``` ", " The function is called on the next element `4`. The next accumulator is 4 + 6 ```elixir Enum.reduce([], fn 4, 6 -> 4 + 6 end) ``` ", " 4 + 6 equals 10. ```elixir Enum.reduce([], fn 4, 6 -> 10 end) ``` ", " `10` is the last accumulator value, so [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) returns `10`. ```elixir 10 ``` " ] SmartAnimation.new(0..(Enum.count(frames) - 1), fn i -> Kino.Markdown.new(Enum.at(frames, i)) end) ```` ### Enum.reduce/3 Alternatively, we can provide a default value for the accumulator with [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3). [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3) will call the function on every element, rather than setting the initial accumulator as the first element. Below, we sum all of the numbers in the list, with an initial sum of `10`. ```elixir Enum.reduce([1, 2, 3], 10, fn integer, accumulator -> integer + accumulator end) ``` ### Your Turn Use [Enum.reduce/3](https://hexdocs.pm/elixir/Enum.html#reduce/3) or [Enum.reduce/2](https://hexdocs.pm/elixir/Enum.html#reduce/2) to sum all of the even numbers from `1` to `10`. It should return `30`. <!-- livebook:{"force_markdown":true} --> ```elixir 2 + 4 + 6 + 8 + 10 = 30 ``` <details style="background-color: lightgreen; padding: 1rem; margin: 1rem 0;"> <summary>Example solution</summary> ```elixir Enum.reduce(1..10, 0, fn int, acc -> if rem(int, 2) == 0 do acc + int else acc end end) ``` </details> Enter your solution below. ```elixir ``` ## Enum.filter The [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2) function allows us to filter elements in a collection. [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2) calls the function with each element in the collection. If the function returns `false` then the element is filtered out. ```mermaid flowchart LR C[Collection] --> E[Enum.filter] E --> F[Function] F -- boolean --> E F --> true --> A[Keep] F --> false --> B[Remove] E --> O[Filtered Collection] ``` ```elixir Enum.filter([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], fn integer -> integer <= 5 end) ``` ### Your Turn use [Enum.filter/2](https://hexdocs.pm/elixir/Enum.html#filter/2) to create a list of odd numbers from `1` to `10` and a list of even numbers from `1` to `10`. <details style="background-color: lightgreen; padding: 1rem; margin: 1rem 0;"> <summary>Example Solution</summary> ```elixir even_numbers = Enum.filter(1..10, fn integer -> rem(integer, 2) == 0 end) odd_numbers = Enum.filter(1..10, fn integer -> rem(integer, 2) != 0 end) ``` </details> Enter your solution below. ```elixir ``` ## Enum.all?/2 [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) checks that all elements in a collection match some condition. [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) executes the callback function provided on each element. If every element returns truthy, then [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) returns `true`. <!-- livebook:{"break_markdown":true} --> ```mermaid flowchart LR Collection --> E[Enum.all?/2] E --> Function Function -- truthy --> E E --> Boolean ``` ```elixir Enum.all?([1, 2, 3], fn integer -> is_integer(integer) end) ``` If a single element returns a falsy value, then [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) returns `false`. ```elixir Enum.all?([1, 2, 3, "4"], fn element -> is_integer(element) end) ``` For performance reasons, [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) will complete as soon as it finds a single element that returns a falsey value when called with the function. Notice the code below should finish very quickly because the very first element fails the condition. ```elixir Enum.all?(1..10_000_000, fn integer -> is_bitstring(integer) end) ``` If [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) must traverse the entire collection if all elements pass the condition, or if a failing element is towards the end of the list. Notice the code below should take awhile to finish running because every element passes the condition. ```elixir Enum.all?(1..10_000_000, fn integer -> is_integer(integer) end) ``` ### Your Turn Use [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2) to determine if all of the `colors` in this list of colors are `:green`. You may change the value of `colors` to experiment with [Enum.all?/2](https://hexdocs.pm/elixir/Enum.html#all?/2). ```elixir colors = [:green, :green, :red] ``` ## Enum.any?/2 [Enum.any?/2](https://hexdocs.pm/elixir/Enum.html#any?/2) checks if any elements in a collection pass some condition. If a single element returns a truthy value when called with the callback function, then [Enum.any?/2](https://hexdocs.pm/elixir/Enum.html#any?/2) returns `true`. <!-- livebook:{"break_markdown":true} --> ```mermaid flowchart LR Collection --> E[Enum.any?/2] E --> Function Function -- truthy --> E E --> Boolean ``` ```elixir Enum.any?([1, "2", "3"], fn element -> is_integer(element) end) ``` [Enum.any?/2](https://hexdocs.pm/elixir/Enum.html#any?/2) returns as soon as an element in the collection returns a truthy value. Notice the code below finishes very quickly, because the first element in the collection passes the condition. ```elixir Enum.any?(1..10_000_000, fn integer -> is_integer(integer) end) ``` However, the following takes awhile to run because all elements in the collection fail the condition. ```elixir Enum.any?(1..10_000_000, fn integer -> is_bitstring(integer) end) ``` ### Your Turn Use [Enum.any?/2](https://hexdocs.pm/elixir/Enum.html#any?/2) to determine if any of the animals in the `animals` list are `:dogs`. You may change the `animals` list to experiment with [Enum.any?/2](https://hexdocs.pm/elixir/Enum.html#any?/2). ```elixir animals = [:cats, :dogs, :bears, :lions, :penguins] ``` ## Enum.count/1 [Enum.count/1](https://hexdocs.pm/elixir/Enum.html#count/1) returns the number of items in a collection. ```mermaid flowchart LR Collection --> Enum.count --> Integer ``` ```elixir Enum.count([1, 2, 3]) ``` The type of elements does not matter. Collections with multiple elements still only count as a single individual element. ```elixir Enum.count([{}, "hello", %{}, [[[]]]]) ``` ### Your Turn In the Elixir cell below, count the number of elements in the `collection`. It should return `5`. ```elixir collection = [1, 2, 3, 4, 5] ``` ## Enum.find/3 [Enum.find/3](https://hexdocs.pm/elixir/Enum.html#find/3) takes in a collection and a function. Then searches the collection and returns the first element that returns true when called as the argument to the passed-in function. ```elixir Enum.find(["hello", 2, 10], fn each -> is_integer(each) end) ``` If no element is found, [Enum.find/2](https://hexdocs.pm/elixir/Enum.html#find/2) returns `nil`. ```elixir Enum.find(["h", "e", "l", "l", "o"], fn each -> is_integer(each) end) ``` You might notice the arity of the function is `3` even though we passed in only `2` arguments. That's because there's an optional `default` value argument. The `default` value will be returned instead of `nil` if no element is found. ```elixir Enum.find(["h", "e", "l", "l", "o"], 10, fn each -> is_integer(each) end) ``` ### Your Turn Use [Enum.find/2](https://hexdocs.pm/elixir/Enum.html#find/2) to find the first even integer in this list. ```elixir [1, "2", "three", 4, "five", 6] ``` ## Enum.random/1 [Enum.random/1](https://hexdocs.pm/elixir/Enum.html#random/1) returns a random element in a collection. It's often used to generate random numbers in a range. ```elixir Enum.random(1..10) ``` ### Your Turn Generate a list with ten random integers from `0` to `9`. <details style="background-color: lightgreen; padding: 1rem; margin: 1rem 0;"> <summary>Example solution</summary> ```elixir Enum.map(1..10, fn _ -> Enum.random(0..9) end) ``` </details> Enter your solution below. ```elixir ``` ## Capture Operator And Module Functions When we provide a function to any of the [Enum](https://hexdocs.pm/elixir/Enum.html) we're passing an anonymous function, which will be called under the hood. We'll bind this function to a variable and inspect every value to demonstrate. ```elixir my_function = fn element -> IO.inspect(element) end Enum.map(1..10, my_function) ``` We can use the capture operator `&` syntax to provide module functions. ```elixir defmodule NonAnonymous do def function(element) do IO.inspect(element) end end Enum.map(1..10, &NonAnonymous.function/1) ``` This can be used with any of Elixir's built-in functions as well, as long as their arity matches the callback function. ```elixir Enum.map(1..10, &is_integer/1) ``` We can also use the capture operator alone to create an anonymous function. However, we generally don't recommend this as it typically reduces readability. `&1` is the first argument to the function. ```elixir Enum.map(1..10, &(&1 * 2)) ``` ## Further Reading The [Enum](https://hexdocs.pm/elixir/Enum.html) module has many more functions. You'll have the opportunity to encounter more as you need them to solve future challenges. For more information, you may also wish to read: * [The Enum Documentation](https://hexdocs.pm/elixir/Enum.html) * [Elixir Schools Enum](https://elixirschool.com/en/lessons/basics/enum) We have several exercises dedicated to the [Enum](https://hexdocs.pm/elixir/Enum.html) module as part of this curriculum. However, if you wish for more practice [Exercism.io](https://exercism.org/tracks/elixir/concepts/enum) has a number of excellent exercises. ## Commit Your Progress DockYard Academy now recommends you use the latest [Release](https://github.com/DockYard-Academy/curriculum/releases) rather than forking or cloning our repository. Run `git status` to ensure there are no undesirable changes. Then run the following in your command line from the `curriculum` folder to commit your progress. ``` $ git add . $ git commit -m "finish Enum reading" $ git push ``` We're proud to offer our open-source curriculum free of charge for anyone to learn from at their own pace. We also offer a paid course where you can learn from an instructor alongside a cohort of your peers. We will accept applications for the June-August 2023 cohort soon. ## Navigation <div style="display: flex; align-items: center; width: 100%; justify-content: space-between; font-size: 1rem; color: #61758a; background-color: #f0f5f9; height: 4rem; padding: 0 1rem; border-radius: 1rem;"> <div style="display: flex;"> <i class="ri-home-fill"></i> <a style="display: flex; color: #61758a; margin-left: 1rem;" href="../start.livemd">Home</a> </div> <div style="display: flex;"> <i class="ri-bug-fill"></i> <a style="display: flex; color: #61758a; margin-left: 1rem;" href="https://github.com/DockYard-Academy/curriculum/issues/new?assignees=&labels=&template=issue.md&title=Enum">Report An Issue</a> </div> <div style="display: flex;"> <i class="ri-arrow-left-fill"></i> <a style="display: flex; color: #61758a; margin-left: 1rem;" href="../reading/ranges.livemd">Ranges</a> </div> <div style="display: flex;"> <a style="display: flex; color: #61758a; margin-right: 1rem;" href="../exercises/fizzbuzz.livemd">FizzBuzz</a> <i class="ri-arrow-right-fill"></i> </div> </div>
See source

Have you already installed Livebook?

If you already installed Livebook, you can configure the default Livebook location where you want to open notebooks.
Livebook up Checking status We can't reach this Livebook (but we saved your preference anyway)
Run notebook

Not yet? Install Livebook in just a minute

Livebook is open source, free, and ready to run anywhere.

Run on your machine

with Livebook Desktop

Run in the cloud

on select platforms

To run on Linux, Docker, embedded devices, or Elixir’s Mix, check our README.

PLATINUM SPONSORS
SPONSORS
Code navigation with go to definition of modules and functions Read More ×