10 killer Elixir Tips #1

Feb 17, 2017 . 3 mins read

If you prefer to watch than read, check out the following video




1 Multiple [OR]

Regular Approach

find = fn(x) when x>10 or x<5 or x==7 -> x end

Our Hack

hack = fn(x) when true in [x>10, x<5, x==7] -> x end

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

This is just good for discoveries.

2. i( term)

It prints the information about a data type of given term. Try that in iex and see the magic.

iex> i(1..5)

3. iex Custom Configuration

Save the following file as .iex.exs in your ~ home directory and see the magic.

# .iex.exs filename
# 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
)

IEx Configuration Screenshot

4. Custom Sigils

Each x sigil calls its respective `sigil_x definition. Here x is an variant.

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.Casing.downcase(string)
  def sigil_l(string,[?l]), do: String.Casing.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.Casing.upcase(string)
  def sigil_u(string,[?l]), do: String.Casing.upcase(string) |> String.graphemes
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"]

5. Custom Error Definitions

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.."
** (BugError) I am Bug..

6. Get a Value from Nested Maps

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, [:name, :last_name])   # returns nil when key is not present

7. with statement

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, the unmatched expression result will be 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 data-types like in the following example.

defprotocol Triple do    
  def triple(input)  
end  

#implemening Protocol when integer type is sent
defimpl Triple, for: Integer do    
  def triple(int) do     
    int * 3   
  end  
end   

#implemening Protocol when list type is sent
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"
  1. Exact Ternary
iex> age=23
iex> (age > 18) && :adult || :infant
:adult

iex> age=15
iex> (age > 18) && :adult || :infant
:infant