Introduction to Elixir Programming

Taylor Foxhall

Created: 2017-02-16 Thu 21:19

La Introducción

Elixir es:

  • Un idioma moderno (1.0 lanzó en 2014) con la sintaxis de Ruby
  • Dinámico
  • Compiló y ejecutó en la máquina virtual BEAM

Introduction

Elixir is:

  • A modern language (1.0 was released in 2014) with Ruby-ish syntax
  • Dynamically typed
  • Compiled and ran on the BEAM virtual machine

Basic Syntax

Arithmetic

iex(1)> 2 + 3
5
iex(2)> 2 - 1
1
iex(3)> 2 * 5
10
iex(4)> 3 / 6
0.5
iex(5)> 10 / 2
5.0
iex(6)> div(10, 2)
5
iex(7)> rem(10, 2)
0

Boolean Algebra

iex(8)> -20 || true
-20
iex(9)> false || 42
42
iex(10)> 42 && true
true
iex(11)> !false
true
iex(12)> true and 42
42
iex(13)> false or true
true
iex(14)> not false
true

Note about and and &&

iex(15)> 42 and true
,** (BadBooleanError) expected a boolean on left-side of "and",
  got: 42

iex(15)> not 42
,** (ArgumentError) argument error
:erlang.not(42)

Comparisons

iex(15)> 1 > 2
false
iex(16)> 1 != 2
true
iex(17)> 2 == 2
true
iex(18)> 2 <= 3
true
iex(19)> 2 == 2.0
true
iex(20)> 2 === 2.0
false

Atoms

iex(21)> :foo
:foo
iex(22)> :foo == :bar
false
iex(23)> is_atom(:true)
true
iex(24)> is_boolean(:true)
true
iex(25)> :true === true
true

Strings

iex(26)> "foo"
"foo"
iex(27)> "foo" == "bar"
false
iex(28)> name = "Taylor"
"Taylor"
iex(29)> "Hello " <> name
"Hello Taylor"
iex(30)> "Hello #{name}"
"Hello Taylor"

Collections

Lists

iex(1)> [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex(2)> list = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
# Prepending
iex(3)> ["π"] ++ list
["π", 3.14, :pie, "Apple"]
# Appending
iex(4)> list ++ ["Cherry"]
[3.14, :pie, "Apple", "Cherry"]
iex(5)> list -- [:pie, 4]
[3.14, "Apple"]
iex(2)> list = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex(6)> hd list
3.14
iex(7)> tl list
[:pie, "Apple"]

Tuples

iex(8)> {43, :magic, "White Mage"}
{43, :magic, "White Mage"}
# Often used to return information about a result
iex(9)> File.read("elixir-intro.org")
{:ok, "... presentation ..."}
iex(10)> File.read("elixir-of-life")
{:error, :enoent}

Keyword Lists

iex(11)> [fighter: "Draal", thief: "Rael"]
[fighter: "Draal", thief: "Rael"]
# Same as
iex(12)> [{:fighter, "Draal"}, {:thief, "Rael"}]
[fighter: "Draal", thief: "Rael"]

Maps

iex(13)> character = %{:equipped => "Fists",
...(13)>               "class" => :monk}
%{:equipped => "Fists", "class" => :monk}
iex(14)> character[:equipped]
"Fists"
iex(15)> character["class"]
:monk
iex(16)> character.equipped
"Fists"
iex(17)> character = %{name: "Malcer", hp: 17,
...(17)>               class: :white_mage}
%{class: :white_mage, hp: 17, name: "Malcer"}
iex(18)> %{character | hp: 10}
%{class: :white_mage, hp: 10, name: "Malcer"}
iex(19)> character
%{class: :white_mage, hp: 17, name: "Malcer"}
iex(20)> character.hp
17

Pattern Matching

iex(1)> shopping_list = ["apples", "grapes", "kale"]
["apples", "grapes", "kale"]
iex(2)> [apples, grapes, kale] = shopping_list
["apples", "grapes", "kale"]
iex(3)> apples
"apples"
iex(4)> grapes
"grapes"
iex(5)> kale
"kale"
iex(8)> shopping_list = ["apples", "grapes", "kale"]
["apples", "grapes", "kale"]
iex(9)> [h | t] = shopping_list
["apples", "grapes", "kale"]
iex(10)> h
"apples"
iex(11)> t
["grapes", "kale"]

Control

if, unless

iex(1)> if String.valid?("Hello") do
...(1)>   "Valid String"
...(1)> else
...(1)>   "Invalid String"
...(1)> end
"Valid String"
iex(2)> if "a string value" do
...(2)>   "Truthy"
...(2)> end
"Truthy"
iex(3)> unless is_integer("hello") do
...(3)>   "Not an Int"
...(3)> end
"Not an Int"

case by case basis

iex(1)> case {:ok, "Hello world"} do
...(1)>   {:ok, result} -> result
...(1)>   {:error}      -> "Uh oh!"
...(1)>   _             -> "Catch all"
...(1)> end
"Hello world"

Pins

iex(1)> pie = 3.14
iex(2)> case "cherry pie" do
...(2)>  ^pie -> "Not so tasty"
...(2)>  pie -> "I bet #{pie} is tasty"
...(2)> end
"I bet cherry pie is tasty"

Functions

Anonymous Functions

iex(1)> sum = fn (a, b) -> a + b end
#Function<12.52032458/2 in :erl_eval.expr/5>
iex(2)> sum.(2, 3)
5
iex(3)> sum = &(&1 + &2)
&:erlang.+/2
iex(4)> sum.(2, 3)
5

Endless Possiblities

iex(1)> handle_result = fn
...(1)>   {:ok, result} -> IO.puts "Handling result..."
...(1)>   {:error}      -> IO.puts "An error has occurred!"
...(1)> end
#Function<6.52032458/1 in :erl_eval.expr/5>
iex(2)> some_result = 1
1
iex(3)> handle_result.({:ok, some_result})
Handling result...

iex(4)> handle_result.({:error})
An error has occurred!

Named Functions

# All named functions must belong to a module
defmodule Greeter do
  def hello(name) do
    "Hello, " <> name
  end
end

iex(1)> Greeter.hello("Taylor")
"Hello, Taylor"
# One line functions have a shorter syntax
defmodule Greeter do
  def hello(name), do: "Hello, " <> name
end

Recursion

defmodule Length do
  def of([]), do: 0
  def of([_h | t]), do: 1 + of(t)
end

iex> Length.of([])
0
iex> Length.of([1, 2, 3])
3

Length.of([1, 2, 3])

1 + of([2, 3])

1 + (1 + of([3]))

1 + (1 + (1 + of([])))

1 + (1 + (1 + (0)))

3

Arity

defmodule Greeter2 do
  # hello/0
  def hello(), do: "Hello, anonymous person!"
  # hello/1
  def hello(name), do: "Hello, " <> name
  # hello/2
  def hello(name1, name2), do: "Hello, #{name1} and #{name2}"
end

References