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 😃
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. 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
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 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.
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 ✋
Top comments (0)