Beginning my journey with elixir Part II. Modules, Enum, Loops, Strings, Recursion, Tests.
Tags: elixir, beginners, tutorial
Published: 2021-02-19 00:00:26

So it's time for the second part of my journey with elixir.
I will try to explain in a clear way things I have lastly learned and also show you how to use the newly acquired knowledge to write some simple programs.
That being said, I encourage you to read and learn something really interesting 😃

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hj6dtix5xjv0y98996w7.jpg)


#### 1.Modules
Modules are used to organize functions in their own namespace, it is useful to allocate functions to modules in relation to their functionality.
Example :

```
defmodule Greetings do
 @moduledoc """
  Provides a function `greet/1` to greet a human
  """
  @doc """
  Prints a hello message

  ## Parameters

    - name: String 

  ## Examples

      iex> Greeter.greet("user324")
      "Good morning! user324"

      iex> Greeter.greet("Peter")
      "Good morning! Peter"

  """
  @greeting "Good morning!"

  def greet(name) do
    ~s(#{@greeting} #{name}.)
  end
end

defmodule Greetings2 do
  alias Greetings, as: Hi

  def main do
    Hi.greet("John")
  end
end

```
As you can see I used the @greeting attribute to use it as a greeting in the greet function. The ~s is a sigil. What is it? Here is an answer: Sigils are special syntax to working with literals, you can read more about this [here](https://elixirschool.com/en/lessons/basics/sigils/). I also used the alias to use functions from another module in a different one.

#### 2.Enum
The Enum is a module to work with enumerables. 
I will only show a few functions from this module because it contains over 70 functions. It will be **all?, any?, chunk_every, chunk_by, each, map, min, filter, reduce, sort and uniq** 

-all?

```
iex>Enum.all?(["one","two","three"], fn(x) -> String.length(x) == 4 end)
false
Enum.all?(["one","two","thre"], fn(x) -> String.length(x) == 3 end)
true

```

-any?

```
iex>Enum.any?(["one","two","three"], fn(x) -> String.length(x) == 4 end)
true
Enum.any?(["one","two","thre"], fn(x) -> String.length(x) == 5 end)
false

```
-chunk_every

```
iex>Enum.chunk_every(["one","two","three"], 2) 
[["one", "two"], ["three"]]

```
-chunk_by

```
iex>Enum.chunk_by(["world","universe","hi"], fn(x) -> String.length(x) end) 
[["world"], ["universe"], ["hi"]]

```

-each

```
iex>Enum.each(["How","are","you","?"], fn(x) -> IO.puts(x) end) 
How
are
you
?
:ok


```

-map

```
iex> Enum.map([0, 1, 2, 3], fn(x) -> x * x end)
[0, 1, 4, 9]

```

-min

```
iex> Enum.min([1, 32, 42, -10])
-10
```

-filter

```
iex> Enum.filter([1, 2, 3, 4], fn(x) -> rem(x, 2) == 0 end)
[2, 4]

```

-reduce

```
iex> Enum.reduce(["a","b","c"], fn(x,acc)-> x <> acc end)
"cba"

```
Explanation: acc is the first element of the list.
This how it works:

```
1. x = 'b' acc = 'a' -> out: "ba"
2. x = 'c' acc = "ba" -> out: "cba"
"cba"

```
-sort

```
iex> Enum.sort([%{:val => 4}, %{:val => 1}], fn(x, y) -> x[:val] > y[:val] end)
[%{val: 4}, %{val: 1}]

```
-uniq

```
iex>  Enum.uniq([1, 2, 3, 2, 1, 1, 1, 1, 1])
[1, 2, 3]

```
#### 3.Loops
-for loop
```

iex>for {_key, val} <- [one: 1, two: 2, three: 3], do: IO.puts _key

one
two
three

```
_______________________

```
iex> import Integer
Integer
iex> for x <- 1..20, is_even(x), do: IO.puts x
2
4
6
8
10
12
14
16
18
20

```
-functional approach [source](https://www.tutorialspoint.com/elixir/elixir_loops.htm)

```

defmodule Loop do
   def print_multiple_times(msg, n) when n <= 1 do
      IO.puts msg
   end

   def print_multiple_times(msg, n) do
      IO.puts msg
      print_multiple_times(msg, n - 1)
   end
end

```
Results :

```
iex> c("file.ex")
[Loop]
iex> Loop.print_multiple_times("HI",3)
HI
HI
HI
:ok
```

#### 4.Strings

-You can use ASCII to assign a string value.

```
iex> string = <<104,101,108,108,111>>
"Hello"

```
-Easy for returning an ASCII value of a char :

```
iex>?a
97

```
[Anagram](https://en.wikipedia.org/wiki/Anagram) program :

```
defmodule Anagram do
  def anagrams?(a, b) when is_binary(a) and is_binary(b) do
    sort_string(a) == sort_string(b)
  end

  def sort_string(string) do
    string
    |> String.downcase()
    |> String.graphemes()
    |> Enum.sort()
  end
end

```
Useful link  [grapheme](https://en.wikipedia.org/wiki/Grapheme).

#### 5.Short view of recursion.

```
defmodule Rec do
  def rec(a,b) do
    if a<=b do
      IO.puts "Hi #{a}"
      a = a + 1
      rec(a,b)
    end
  end
end

```
Results: 

```
[Rec]
iex> Rec.rec(2,7)
Hi 2
Hi 3
Hi 4
Hi 5
Hi 6
Hi 7
nil

```
#### 6. Tests

I wrote a simple program and I hope that  it will be useful in understanding the methods of testing.

```
defmodule App do

    def get_name do
      IO.gets("What is yout name? ")
      |>String.trim
    end

    def get_number do
      IO.getn("Give a number: [0-9] ",1)
    end

    def main() do
      name = get_name()
      IO.puts("Hello #{name}")
      number = get_number()
      name
    end

end

ExUnit.start

defmodule Tests do
  alias App
  use ExUnit.Case

  test "check if name is valid" do
    refute String.match?(App.main,~r/[0-9]/)
  end
end

```
Explanation: IO.getn(string,size) , ~r/[0-9]/ (regex);

Before testing, you have to launch it by ExUnit.start, 
to use the test condition I had to write before it _use ExUnit.Case_. ' _refute String.match?(App.main,~r/[0-9]/)_ '
refute it is the same as unless, you can also use assert in testing which means 'should' or 'expect to be' .

Result:

```
What is your name? qwer45
Hello qwer45
Give a number: [0-9] 5

1) test check if name is valid (Tests)
     tests.exs:27
     Expected false or nil, got true
     code: refute String.match?(App.main, ~r"[0-9]")
     arguments:

         # 1
         "qwer45"

         # 2
         ~r/[0-9]/

     stacktrace:
       tests.exs:28: (test)



Finished in 4.8 seconds (0.07s on load, 4.7s on tests)
1 test, 1 failure


```
This all for part II in the next part I plan to write about using dates and times, custom mix tasks, more about iex, error handling, and executable files. Have a nice day ✋