- Elixir tips
- Spliting strings with sigils
- Creating an array containing the alphabet
- Multiple expressions on single line
- Finding list of bound values in iex
- Integer to float
- If/else alternative
- Multiple OR
- Inspecting data types
- Creating custom sigils
- Custom errors
- Get a value from nested maps
with
statement benefits- Using module
Kernel
with pipelines - Short circuit operators
&&
and||
- Finding substrings
- Check if a module is loaded or not
- Binary to capital atom
- Pattern match VS destructure
- Inspect with :label
- Subtraction over lists
- Aliasing multiple modules
- Substring
- Initializing multiple with same value
- Checking the closeness of strings
- Chain of OR in guards
- Replacing a key in a map
- Generate 4 digit random number
iex> text = "foo bar"
iex> ~w/#{text}/
["foo", "bar"]
A char list containing the alphabet can be obtained by doing the following:
iex> for n <- ?a..?z, do: n
'abcdefghijklmnopqrstuvwxyz'
If desired, we can pass each bitcode to a binary to represent each letter as a string:
iex> for n <- ?a..?z, do: << n :: utf8 >>
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p","q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
x=1; y=2; z=3; a=4; b=5; c=6; d=7; e=8; f=9;
iex> binding
[]
iex> name = "blackode"
"blackode"
iex> blog = "medium"
"medium"
iex> binding
[blog: "medium", name: "blackode"]
iex> 5/1
5.0
iex> 5+0.0
5.0
iex(1)> x = 7
7
iex(2)> y=10
10
iex(3)> greatest = x>y && x || y
10
iex(4)> smallest = x<y && x || y
7
This is not the recommended approach because in regular approach when the condition evaluates to true , it stops executing the remaining conditions which saves time of evaluation unlike this approach which evaluates all conditions first in list. This is just bad but good for discoveries.
- Regular Approach
find = fn(x) when x>10 or x<5 or x==7 -> x end
- Our Hack
hell = fn(x) when true in [x>10, x<5, x==7] -> x end
Prints information about the data type of any given term.
iex> i Hello
Term
Hello
Data type
Atom
Raw representation
:"Elixir.Hello"
Reference modules
Atom
Implemented protocols
IEx.Info, Inspect, List.Chars, String.Chars
defmodule MySigils do
# returns the downcasing string if option l
# is given then returns the list of downcase letters
def sigil_l(string, []), do: String.downcase(string)
def sigil_l(string, [?l]) do
string
|> String.downcase()
|> String.graphemes()
end
# returns the upcasing string if option l
# is given then returns the list of downcase letters
def sigil_u(string, []), do: String.upcase(string)
def sigil_u(string, [?l]) do
string
|> String.upcase()
|> String.graphemes()
end
end
usage:
iex> import MySigils
iex> ~l/HELLO/
"hello"
iex> ~l/HELLO/l
["h", "e", "l", "l", "o"]
iex> ~u/hello/
"HELLO"
iex> ~u/hello/l
["H", "E", "L", "L", "O"]
# bug_error.ex
defmodule BugError do
defexception message: "BUG BUG .." # message is the default
end
usage:
$ iex bug_error.ex
iex> raise BugError
** (BugError) BUG BUG ..
iex> raise BugError, message: "I am Bug.." #here passing the message dynamic
** (BugError) I am Bug..
iex> nested_map = %{name: %{first_name: "blackode"}}
# Retrieving the Key:
iex> get_in(nested_map, [:name, :first_name])
"blackode"
iex> get_in(nested, [:name, :last_name])
nil
# returns nil when key is not present
The special form with is used to chain a sequence of matches in order and finally return the result of do: if all the clauses match. However, if one of the clauses does not match, its result of the miss matched expression is immediately returned.
iex> with 1 <- 1+0,
...> 2 <- 1+1,
...> do: IO.puts "all matched"
"all matched"
iex> with 1 <- 1+0,
...> 2 <- 3+1,
...> do: IO.puts "all matched"
4
# since 2 <- 3+1 is not matched so the result of 3+1 is returned
:input
|> do_something
|> do_another_thing
|> Kernel.||(:default_output) # <-- This line
|> do_something_else
These replaces the nested complicated conditions. These are my best friends in the situations dealing with more complex comparisons.
The ||
operator always returns the first expression which is true. Elixir doesn’t care about the remaining expressions, and won’t evaluate them after a match has been found.
iex> false || nil || :blackode || :elixir || :jose
:blackode
Here if you observe the first expression is false next nil is also false in elixir next :blackode
which evaluates to true and its value is returned immediately with out evaluating the :elixir
and :jose
. Similarly if all the statements evaluates to false the last expression is returned.
iex> true && :true && :elixir && 5
5
iex> nil && 100
nil
iex> salary = is_login && is_admin && is_staff && 100_000
This &&
returns the second expression if the first expression is true or else it returns the first expression with out evaluating the second expression. In the above examples the last one is the situation where we encounter to use the &&
operator.
iex> "blackode" =~ "kode"
true
iex> "blackode" =~ "medium"
false
iex> "blackode" =~ ""
true
iex> Code.ensure_loaded?(:kernel)
true
iex> Code.ensure_loaded(:kernel)
{:module, :kernel}
Similarly we are having ensure_compile to check whether the module is compiled or not…
iex> String.to_atom("Blackode")
:Blackode
iex> Module.concat(Elixir,"Blackode")
Blackode
We all know that =
does the pattern match for left and right side. We cannot do [a, b, c] = [1, 2, 3, 4]
this raise a MatchError
iex> [a, b, c] = [1, 2, 3, 4]
** (MatchError) no match of right hand side value: [1, 2, 3, 4]
We can use destructure/2 to do the job.
iex> destructure [a, b, c], [1, 2, 3, 4]
[1, 2, 3]
iex> {a, b, c}
{1, 2, 3}
If the left side is having more entries than in right side, it assigns the nil value for remaining entries..
iex> destructure([a, b, c], [1])
[1, nil, nil]
iex> {a, b, c}
{1, nil, nil}
iex> IO.inspect [1, 2, 3], label: "the list"
the list: [1, 2, 3]
[1, 2, 3]
iex> [1, 2, 3, 4] -- [1, 2]
[3, 4]
iex> [1, 2, 3, 4, 1] -- [1]
[2, 3, 4, 1]
iex> [1, 2, 3, 4, 1] -- [1, 1]
[2, 3, 4]
iex> [1, 2, 3, 4] -- [6]
[1, 2, 3, 4]
iex> 'blackode' -- 'ode'
'black'
iex> 'blackode' -- 'z'
'blackode'
iex> 'blackode' -- 'hello'
'backd'
alias Hello.{One,Two,Three}
# The above line is same as the following:
alias Hello.One
alias Hello.Two
alias Hello.Three
iex> String.slice("blackode", 1..-1)
"lackode"
iex> String.slice("blackode", 0..-4)
"black"
iex> x = y = z = 5
5
iex> {x, y, z}
{5, 5, 5}
iex> String.jaro_distance("ping", "pong")
0.8333333333333334
iex> String.jaro_distance("color", "colour")
0.9444444444444445
iex> String.jaro_distance("foo", "foo")
1.0
# This returns a float value in the range 0..1
def print_me(thing)
when is_integer(thing)
when is_float(thing)
when is_nil(thing) do
"I am a number"
end
details = %{name: "john", address1: "heaven", id1: 42}
%{address1: "heaven", id1: 42, name: "john"}
iex> Map.new(details, fn
{:address1, address} -> {:address, address}
{:id1, id} -> {:phone, id}
x -> x
end)
# output
%{address: "heaven", name: "john", phone: 42}
# 0001..9999
"~4..0B"
|> :io_lib.format([:rand.uniform(10_000) - 1])
|> List.to_string()