Part- 1

1. Multiple [ OR ]

This is just the other way of writing Multiple OR conditions. 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

2. i( term) Elixir Term Type and Meta Data

Prints information about the data type of any given term. Try that in iex and see the magic.

iex> i(1..5)

3. iex Custom Configuration - iex Decoration

Copy the content into a file and save the file as .iex.exs in your ~ home directory and see the magic. You can also download the file HERE

# IEx.configure colors: [enabled: true]
# IEx.configure colors: [ eval_result: [ :cyan, :bright ] ]
IO.puts IO.ANSI.red_background() <> IO.ANSI.white() <> " ❄❄❄ Good Luck with Elixir ❄❄❄ " <> IO.ANSI.reset
Application.put_env(:elixir, :ansi_enabled, true)
IEx.configure(
colors: [
eval_result: [:green, :bright] ,
eval_error: [[:red,:bright,"Bug Bug ..!!"]],
eval_info: [:yellow, :bright ],
],
default_prompt: [
"\e[G", # ANSI CHA, move cursor to column 1
:white,
"I",
:red,
"❤" , # plain string
:green,
"%prefix",:white,"|",
:blue,
"%counter",
:white,
"|",
:red,
"▶" , # plain string
:white,
"▶▶" , # plain string
# ❤ ❤-»" , # plain string
:reset
] |> IO.ANSI.format |> IO.chardata_to_string
)
img

4. Creating Custom Sigils and Documenting

Each x sigil call respective sigil_x definition

Defining Custom Sigils

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.downcase(string) |> String.graphemes
#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.upcase(string) |> String.graphemes
end

usage

Load the module into iex

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"]

5. Custom Error Definitions

Define Custom Error

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..

6. Get a Value from Nested Maps Easily

The get_in function can be used to retrieve a nested value in nested maps using a list of keys.

nested_map = %{ name: %{ first_name: "blackode"} } # Example of Nested Map
first_name = get_in(nested_map, [:name, :first_name]) # Retrieving the Key
# Returns nil for missing value
nil = get_in(nested_map, [:name, :last_name]) # returns nil when key is not present

Read docs: Kernel.get_in/2

7. With Statement Benefits

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

8. Writing Protocols

Define a Protocol

A Protocol is a way to dispatch to a particular implementation of a function based on the type of the parameter. The macros defprotocol and defimpl are used to define Protocols and Protocol implementations respectively for different types in the following example.

defprotocol Triple do
def triple(input)
end
defimpl Triple, for: Integer do
def triple(int) do
int * 3
end
end
defimpl Triple, for: List do
def triple(list) do
list ++ list ++ list
end
end

Usage

Load the code into iex and execute

iex> Triple.triple(3)
9
Triple.triple([1, 2])
[1, 2, 1, 2, 1, 2]

9. Ternary Operator

There is no ternary operator like true ? "yes" : "no" . So, the following is suggested.

"no" = if 1 == 0, do: "yes", else: "no"

10. Advantage of Kernel.||

When using pipelines, sometimes we break the pipeline for or operation. For example:

result = :input
|> do_something
|> do_another_thing
# Bad
result = (result || :default_output)
|> do_something_else

Indeed, || is only a shortcut for Kernel.|| . We can use Kernel.|| in the pipeline instead to avoid breaking the pipeline.

The code above will be:

result = :input
|> do_something
|> do_another_thing
|> Kernel.||(:default_output) #<-- This line
|> do_something_else

This above tip is from qhwa