Slide 1

Slide 1 text

Elixir Jean-Marcel Belmont Raleigh Elixir Users Group

Slide 2

Slide 2 text

What is Elixir? Elixir is a dynamic, functional language designed for building scalable and maintainable applications. Elixir leverages the Erlang VM, known for running low- latency, distributed and fault-tolerant systems, while also being successfully used in web development and the embedded software domain. — http://www.elixir-lang.org

Slide 3

Slide 3 text

Misconceptions about Elixir Elixir is CoffeeScript for Erlang Ruby on Rails Type Development for Erlang Erlang beefed with nicer syntax and some tools

Slide 4

Slide 4 text

Why Elixir? Chip designers are under so much pressure to deliver ever-faster CPUs that they’ll risk changing the meaning of your program, and possibly break it, in order to make it run faster http://www.gotw.ca/publications/concurrency-ddj.htm The Free Lunch Is Over A Fundamental Turn Toward Concurrency in Software By Herb Sutter

Slide 5

Slide 5 text

Companies using Erlang ● Amazon ● Yahoo ● Facebook ● T-Mobile ● Motorola ● VMWare ● Heroku ● Ericsson ● WhatsApp ● CouchDB ● Github ● Basho ● Call of Duty

Slide 6

Slide 6 text

Solution? ⇒ Functional Programming Pure Functions are stateless. Pure Functions always produces the same output for a particular input. Programming Order of Execution doesn't matter. Common pitfalls of concurrent environments such as deadlocks, race conditions, etc. related to order of execution can be avoided much more easily. Stateless functions are easier to reason about. Result ⇒ DeadLocks, Mutexes, Semaphores ⇒ Gone

Slide 7

Slide 7 text

Benefits of Pure Functions Laziness: Only Evaluate when output is needed Memoization ⇒ is a specific form of caching that involves caching the return value of a function based on its parameters No Order Dependencies ⇒ Evaluate statements in any order Easily Parallelizable [Immutability, No Side Effects, Memoizable, Laziness] ⇒ Concurrency Problem Goes Away

Slide 8

Slide 8 text

Aspects of Functional Programming Immutable Data Structures Functional Composition ⇒ In computer science, function composition (not to be confused with object composition) is an act or mechanism to combine simple functions to build more complicated ones. Function Currying ⇒ the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed. Pattern Matching

Slide 9

Slide 9 text

Here Comes Elixir Sample Elixir Programs: defmodule Factorial do def of(0), do: 1 def of(n) when n > 0 do n * of(n-1) end end defmodule Fibonacci do def fibonnaci(n) do when n == 0, do: 0 when n == 1, do: 1 when n > 1 do fibonnaci(n - 2) + fibonnaci(n - 1) end end end

Slide 10

Slide 10 text

Comments and documentation # Comments in elixir begin like this @moduledoc """ Multiline Syntax documentation for modules in Elixir. Once you compile an Elixir Program you can run “h ModuleName” """ @doc """ Multiline syntax documentation for functions and run h ModuleName.somefunction """

Slide 11

Slide 11 text

Basic Types in Elixir Integer ⇒ 1234 0xcafe 0177 0b100 0o77 10_000 # x marks hexadecimal, b marks binary, o mark octal, underscore is separator Float ⇒ 1.0 3.1415 6.02e23 # must be prefixed with digit so cannot have .3 Atom ⇒ :foo :me@home :"with spaces" # Strings and Char Lists "hello" # string 'hello' # char list # Multi-line strings ⇒ # "I'm a multi-line\nstring.\n" """ I'm also a multi-line string. """

Slide 12

Slide 12 text

Math Operators # Math Operators 1 + 1 #=> 2 10 - 5 #=> 5 5 * 2 #=> 10 10 / 2 #=> 5.0 #=> In elixir the operator `/` always returns a float. # To do integer division use `div` div(14, 2) #=> 7 # To get the division remainder use `rem` rem(10, 3) #=> 1

Slide 13

Slide 13 text

Comparison Operators # For comparisons we have: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` and `>` 1 == 1 #=> true 1 != 1 #=> false 1 < 2 #=> true # `===` and `!==` are more strict when comparing integers and floats: 1 == 1.0 #=> true 1 === 1.0 #=> false # We can also compare two different data types: 1 < :hello #=> true

Slide 14

Slide 14 text

Boolean Operators # There are also boolean operators: `or`, `and` and `not`. # These operators expect a boolean as their first argument. true and true #=> true false or true #=> true # 1 and true #=> ** (ArgumentError) argument error # If you are an Erlang developer, and and or in Elixir actually map to the andalso and orelse operators in Erlang. # Elixir also provides `||`, `&&` and `!` which accept arguments of any type. # All values except `false` and `nil` will evaluate to true. 1 || true #=> 1 false && 1 #=> false nil && 20 #=> nil !true #=> false

Slide 15

Slide 15 text

Data Structures, Binaries, Strings Tuple ⇒ { 1, 2, :ok, "xy" } # Array Like Data Structure List ⇒ [ 1, 2, 3 ] # Similar to Linked List [head | tail] Keyword List ⇒ (can have duplicate keys) ⇒ [ a: "Foo", b: 123 ] Map ⇒ (cannot have duplicate keys) ⇒ %{ key => value, key => value } Binary ⇒ << 1, 2 >> or "abc" # Strings are really just binaries, while Char lists are just Lists. String Interpolation ⇒ "I am an #{interpolated_string}" Truth Operators ⇒ true, false, nil Range Operator ⇒ a..b

Slide 16

Slide 16 text

Miscellaneous Operators # String concatenation binary1 <> binary2 #=> “Hello” <> “World” ⇒ “HelloWorld” # List Concatenation list1 ++ list2 #=> [1, 2] ++ [3, 4] ⇒ [1, 2, 3, 4] # Set Difference list1 -- list2 #=> [1, 2, 3] -- [2] ⇒ [1, 3] # Membership operator a in enum #=> 1 in [1, 2, 3] ⇒ true Restrict Re-assignment operator ^term #=> x = 1, 1 = x, but then ^x = 2 ⇒ ** (MatchError) no match of right hand side value: 2

Slide 17

Slide 17 text

Control Flow # `if` expression if false do "This will never be seen" else "This will" end # There's also `unless` unless true do "This will never be seen" else "This will" end # `cond` lets us check for many conditions at the same time. # Use `cond` instead of nesting many `if` expressions. # cond uses pattern matching cond do 2 + 4 == 3 -> "I will never be seen" 2 * 5 == 12 -> "Me neither" 1 + 2 == 3 -> "But I will" end

Slide 18

Slide 18 text

Pattern Matching # Many control-flow structures in Elixir rely on Pattern Matching. # `case` allows us to compare a value against many patterns: case {:one, :two} do {:four, :five} -> "This won't match" {:one, x} -> "This will match and bind `x` to `:two`" _ -> "This will match any value" end

Slide 19

Slide 19 text

Error Handling Operators # `try/catch` is used to catch values that are thrown, it also supports an # `after` clause that is invoked whether or not a value is caught. try do throw(:hello) catch message -> "Got #{message}." after IO.puts("I'm the after clause.") end # In Elixir, we avoid using try/rescue because we don't use errors for control flow. We take errors literally: they are reserved to unexpected and/or exceptional situations. # Let it fail is the Elixir/Erlang model

Slide 20

Slide 20 text

Sigils in Elixir Sigils provide Language facility for developers to extend the languages features The most common sigil in Elixir is ~r, which is used to create regular expressions regex = ~r/foo|bar/ # A regular expression that matches strings which contain "foo" or "bar "foo" =~ regex #=> true “buzz” =~ regex #=> false 8 different delimiters you can use with sigils ~r/hello/ ~r|hello| ~r"hello" ~r'hello' ~r(hello) ~r[hello] ~r{hello} ~r Sigils also support heredocs, that is, triple double- or single-quotes as separators The ~s sigil is used to generate strings ⇒ ~s(this is a string with "double" quotes, not 'single' ones) ⇒ "this is a string with \"double\" quotes, not 'single' ones" The ~c sigil used to generate char lists ⇒ ~c(this is a char list containing 'single quotes') 'this is a char list containing \'single quotes\'' The ~w sigil is used to generate lists of words that are delimited by white space ~w(foo bar bat) ⇒ ["foo", "bar", "bat"] Custom Sigils can be made with sigil_{identifier} pattern

Slide 21

Slide 21 text

Anonymous Functions in Elixir # Anonymous functions (notice the dot) square = fn(x) -> x * x end square.(5) #=> 25 # Anonymous functions with clauses and guards. # Guards let you fine tune pattern matching, # they are indicated by the `when` keyword: f = fn x, y when x > 0 -> x + y x, y -> x * y end #=> iex: f.(1, 3) #=> 4 #=> iex: f.(-1, 3) #=> -3

Slide 22

Slide 22 text

Builtin Functions in Elixir # Elixir also provides many built-in functions. # These are available in the current scope. is_number(10) #=> true is_list("hello") #=> false elem({1,2,3}, 0) #=> 1 div(2, 2) #=> 1 rem(4, 3) #=> 1 # Many others in http://elixir-lang.org/docs/stable/elixir/

Slide 23

Slide 23 text

Named Function in Elixir # You can group several functions into a module. # Inside a module use `def` to define your functions. defmodule MathStuff do def sum(a, b) do a + b end def square(x) do x * x end def power_of_3(z), do: z * z * z end

Slide 24

Slide 24 text

Shortcut Function Syntax # Also called Capture Syntax square = fn(x) -> x * x end square = &(&1 * &1) #=> square.(3) ⇒ 9 string_concat = &(&1 <> &2) #=> string_concat.(“Hello”, “World”) ⇒ “HelloWorld” fun = &List.flatten(&1, &2) # You can also capture Custom Modules fun.([1, [[2], 3]], [4, 5]) &List.flatten(&1, &2) is the same as writing fn(list, tail) -> List.flatten(list, tail) end

Slide 25

Slide 25 text

Custom Module Definition # You can group several functions into a module. # Inside a module use `def` to define functions. defmodule Math do defmodule Math do def sum(a, b) do def sum(a,b), do: &(&1 + &2) a + b end def square(x), do: &(&1 * &1) end def square(x) do x * x end end Math.sum(3, 5) #=> 8

Slide 26

Slide 26 text

Recursion in Elixir # Recursion is used often in Elixir defmodule RecursionFunctions do @doc “”” Function sums up all the elements of an empty list “”” def sum_list([head | tail], acc) do sum_list(tail, acc + head) end def sum_list([], acc) do acc end end # Recursion.sum_list([5,4,3], 0) #=> 12

Slide 27

Slide 27 text

Attributes in Elixir # Elixir modules support attributes, there are built-in attributes # You can also define your own attributes defmodule AttributeExample do @moduledoc """ This is a built-in attribute on an attribute example module. """ @eighty_nine 89 # This is a custom attribute. def add_attribute(x) do @eighty_nine + x end IO.inspect(@eighty_nine) #=> 89 end

Slide 28

Slide 28 text

Structs in Elixir # Structs are extensions on top of maps that bring default values, # Structs are just bare maps underneath # Structs bring compile-time guarantees and polymorphism into Elixir. defmodule Person do defstruct name: nil, age: 0, height: 0 # only can define one struct at a time end some_dude = %Person{ name: "Marcel", age: 34, height: 240 } some_dude.name #=> Marcel some_gal = %{ some_dude | name: "Catherine", age: 22, height: 119 }

Slide 29

Slide 29 text

Macros in Elixir # Implement unless using if defmodule MacroExample do defmacro unless(clause, options) do quote do: if(!unquote(clause), unquote(options)) end end # macros must be required before invoked require MacroExample MacroExample.unless false do IO.puts “Here I am now” end

Slide 30

Slide 30 text

Protocols in Elixir ● Protocols are a mechanism to achieve polymorphism in Elixir defprotocol Blank do @doc "Returns true if data is considered blank/empty" def blank?(data) end # Integers are never blank defimpl Blank, for: Integer do def blank?(_), do: false end # Just empty list is blank defimpl Blank, for: List do def blank?([]), do: true def blank?(_), do: false end

Slide 31

Slide 31 text

Enumerables in Elixir # Enumurable example map_list_of_nums = Enum.map(1..3, fn x -> x * 2 end) #=> [2, 4, 6] map_list_of_nums = Enum.map(1..3, &(&1 * 2)) #=> [2, 4, 6] odd? = &(rem(&1, 2) != 0) # define a function that tests whether number is odd # Ugly form of function chaining Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?)) # The Elixir way 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum ● All the functions in the Enum module are eager. Many functions expect an enumerable and return a list back

Slide 32

Slide 32 text

Comprehensions in Elixir ● Comprehensions in Elixir allow you to quickly build data structures from ● an enumerable or a bitstring ● iex> for n <- [1, 2, 3, 4, 5], do: n * 3 #=> [3, 6, 9, 12, 15] ● The `<-` is called a generator ● Comprehension can take many generators and filters Example comprehension with 3 generators for x <- [1, 2, 3], y <- [4, 5, 6], z <- [7, 8, 9], rem(n, 2) == 0, do: x * y * z #=> [28, 32, 36, 35, 40, 45, 42, 48, 54, 56, 64, 72, 70, 80, 90, 84, 96, 108, 84, 96, 108, 105, 120, 135, 126, 144, 162] Example comprehension with a filter for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n #=> [2, 4, 6] You can combine both generators and a filter in a comprehension

Slide 33

Slide 33 text

Streams in Elixir ● Streams are lazy, composable enumerables ● Instead of generating intermediate lists, streams create a series of computations that are invoked only when we pass it to the Enum module ● Streams are useful when working with large, possibly infinite, collections. # Stream Example odd? = &(rem(&1, 2) != 0) stream_list_of_nums = 1..100_000_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?) |> Enum.sum

Slide 34

Slide 34 text

Concurrency in Elixir ● Elixir relies on the Actor model for concurrency ● All we need to write concurrent programs in elixir are three primitives: ○ spawning processes, sending messages and receiving messages. ● Actor is a Process ● A process performs a specific task when it receives a message ● After receiving a message it can reply to the sender ● All messages go to a process Queue ○ Messages are in a Queue for unprocessed messages sent from other ○ processes that have not been consumed ● Processes are isolated from each other, run concurrent to one another and communicate via message passing ○ Share-nothing Asynchronous Message Passing ● Distributed systems sometimes called "shared nothing" systems because the message passing abstraction hides underlying state changes that may be used in the implementation of sending messages ### Wikipedia ###

Slide 35

Slide 35 text

Concurrency in Action # To start a new process we use the `spawn` function, which takes a function # as argument. f = fn -> 2 * 2 end spawn(f) #=> #PID<0.40.0> spawn fn -> 2 * 2 end pid = spawn fn -> 1 + 2 end Process.alive?(pid) #=> false # Process.alive?(self()) send self(), {:hello, "world"} receive do {:hello, msg} -> msg {:world, msg} -> "won't match" end #=> “world”

Slide 36

Slide 36 text

Sample Send/Receive Elixir Module # ~spawn~ returns a pid (process identifier), you can use this pid to send messages to the process. # To do message passing we use the ~send~ operator. # Then we need to receive messages that are sent. This is achieved with the `receive` mechanism: defmodule SampleSendReceive do def area_calculation do receive do {:rectangle, w, h} -> IO.puts("Area of rectangle is #{w * h}") area_calculation() {:square, s} -> IO.puts("Area of square is #{s * s}") area_calculation() end end end

Slide 37

Slide 37 text

Sample run of Send/Receive Module # compile program in iex ⇒ c “SampleSendReceive.ex” pid = spawn(fn -> SampleSendReceive.area_calculation() end) # Rectangle pattern matched send pid, {:rectangle, 2, 3} or pid |> send({:rectangle, 2, 3}) #=> Area of rectangle is 6 #=> {:rectangle, 2, 3} # Square pattern matched pid |> send({:square, 3}) #=> Area of square is 9 #=> {:square, 3}

Slide 38

Slide 38 text

Mix Build Tool and Built-in Unit Tests > mix new mt --module Meetup * creating README.md * creating .gitignore * creating mix.exs * creating config * creating config/config.exs * creating lib * creating lib/mt.ex * creating test * creating test/test_helper.exs * creating test/mt_test.exs Your mix project was created successfully. You can use mix to compile it, test it, and more: cd mt; mix test Run `mix help` for more commands.

Slide 39

Slide 39 text

What’s Next More in-depth overview of OTP (Open-Telecom Platform) in Elixir/Erlang Web Framework Library ⇒ Phoenix ORM like Library ⇒ Ecto Package Manager ⇒ Hex Unit Testing in Elixir Lightning Talks

Slide 40

Slide 40 text

Thank You for Attending Please post any questions you may have on the meetup discussion board.