Getting Started with Elixir for Erlang, Ruby programmer

6115584ec4554ed71f17effd3e0b6988?s=47 Altech
November 02, 2015

Getting Started with Elixir for Erlang, Ruby programmer

Presented at 2015-11-02 in PSG Seminar with some demo.

6115584ec4554ed71f17effd3e0b6988?s=128

Altech

November 02, 2015
Tweet

Transcript

  1. Getting Started with Elixir. for Erlang, Ruby programmer 2015-11-02 /

    Sohei Takeno
  2. About Elixir • Run on Erlang VM. • Its mechanism

    is same as Erlang. • Basic data types, module system etc. • Syntax is very similar to Ruby. • Following slides is a digest of Getting Started which assumes readers to know Erlang mechanism and Ruby syntax.
  3. Setup • Install: `brew install elixir` • Start intreactive shell:

    `iex` # Let’s eval codes! • Run Script: `elixir <file>` • Compile: `elixirc <file>`
  4. Data Types

  5. Basic Data Types • integer, float, atom, byte, list, tuple

    • string: as byte string or list of integers. • boolean: as atom’s syntax sugar. • There are same built-in function as Erlang. • is_boolean/1, is_float/1 etc.
  6. # integer 1 # float 1.0 # atom :atom #

    boolean true # list [1,2,3] # tuple {:ok,200} # byte string “Hello World” # list of integers ‘Hello World’ # byte data <<72, 101, 108, 108, 111, 32, 87>> true == :true #=> ? is_byte(“Hello”) #=> ? <<72, 101, 108, 108, 111, 32, 87>> == “Hello” #=> ? hd(‘Hello’) #=> ?
  7. Keyword List • List of pairs of atom and value.

    • [{:a, 1}, {:b, 2}] • There is convenient syntax: • Create: [a: 1, b: 2] • Access: keywords[:a] #=> 1
  8. Map (1) • General key-value data structure. • There is

    convenient syntax: • Create: %{1 => 'a', 2 => ‘b’} • Access: map[1] # => ‘a’ • Update: %{map | :a => 2} • Pattern matching: %{1 => value} = map
  9. Map (2) • Syntax for map using atom for keys:

    • Initialize: %{a: 1, b: 2} • Access: map.a #=> 1 • Map and keyword list implement Dict behavior. • (Behavior is like interface of Java)
  10. Function • Syntax: • Initialize: fn a, b -> a

    + b end • For pattern matching, write multiple 
 “<Arguments Pattern> -> <Expression>”. • Get value o module function: &Enum.map/2 • Call: function_value.(1, 2) #=> 3
  11. Boolean • There are two types of operators. • and,

    or accept only boolean. • &&, || accept any types. • nil and false are recognized as false value.
  12. Control-Flow • case, cond, if, unless • To check a

    value, use case. • To check a condition generally, use cond. • Use if and unless for simple cases.
  13. case {1, 2, 3} do {4, 5, 6} -> "won't

    match" {1, x, 3} -> "will match, and bind x to 2" _ -> "Would match any value" end cond do 1 + 1 == 0 -> “won’t match” 1 + 1 == 2 -> “will match” true -> “default” end if var == 2 do “true clause” else “false clause end
  14. Keyword List as Arguments • Block is implemented as keyword

    list. • For example, is equals to: if 1 == 2 do “foo” else “bar” end if( 1 == 2, do: ”foo”, else: “bar” )
  15. Note: Variable • Variable is beginning lowercase like foo =

    1 • Reassigning new value is valid operation. • To use existing variable as value for pattern matching(e.g. right-hand side of =), Use pin-operator. • ^foo = 2 raise MatchError because foo binds to 1. • foo = 2 binds 2 to foo.
  16. Module System

  17. Module • Syntax: defmodule <Module> do … end • Define

    function: def sum(a,b) do … end • Write multiple def for pattern matching. • Use defp for private function.
  18. # Define a module defmodule MyString do def lowercase(str) do

    # convert to lowercase string end # default value of `sep` is “,” def join(str_list, sep \\ “,") do # joins strings using the separator end end # Call module functions MyString.lowercase("Foo") #=> “foo" MyString.lowercase “Foo" #=> “foo" MyString.join(["Foo", "Bar", "Baz"]) #=> “Foo,Bar,Baz”
  19. About Name Spaces • There are some operation to control

    naming. • alias Math.List as: List • import List, only: [duplicate: 2] • Mechanism of alias and import: • Module name is a atom(That’s all): is_atom(List) #=> true • Elixir add prefix “Elixir.” to module name: List == :”Elixir.List” => ? • So List.last(l) calls last function of module named :”Elixir.List”. • (alias and import simply manipulates these atom)
  20. Protocol • Mechanism for polymorphism • Define: defprotocol Blank do

    … end • Use: defimpl Blank for: String do … end • for: Any add default implementation.
  21. ## Define a protocol defprotocol Blank do def blank?(data) end

    ## Implement a protocol defimpl Blank, for: List do def blank?([]), do: true def blank?(_), do: false end defimpl Blank, for: Any do def blank?(_), do: false end
  22. Behavior • List of functions to implement(from Erlang). • Define:

    write like @callback parse(String.t) :: any in the behavior module (e.g. Parser). • We can use type specification also. • Use: write @behavior Parser in a module
 like JSONParser module. • Then compiler checks the behavior.
  23. Error Handling

  24. try-rescue and raise • Syntax: • Define exception: defexception in

    a module. • Generate exception: raise ErrorModule • Catch: try do … rescue … end • Use try-catch and throw for control-flow
  25. # Define error module defmodule ParseError do defexception message: “This

    is default message” end # Use try do raise ParseError, message: “This is custom message” rescue e in ParseError -> IO.puts “Parse error(#{e.message}) was raised.” end
  26. Other Mechanism from Erlang • Pattern-matching tuple • {:ok, value}

    or {:error, message} • This is major way in Erlnag/Elixir API. • Supervisor tree • exit notify error to supervisor.
  27. Convenient Syntax

  28. Sigils • Mechanism which realizes reg-exp literal. • Like this:

    ~r/https?/i • Interpreted as: sigil_r(“https?”, ‘i’) • Other example: • ~w(foo bar baz) #=> [“foo”, “bar”, “baz”]
  29. Comprehensions • Popular understandable syntax. • Works for Enumerable values

    and byte strings(!). • Functions: Generator, Filter, Collector • Collector works with Collectable values.
  30. # List comprehensions for dir <- dirs, # Generate from

    a list file <- File.ls!(dir), # Generate from a list(for each `dir`) path = Path.join(dir, file), # Binds values File.regular?(path) do # Filter by a predicate File.rm!(path) end # => [:ok, :ok, :ok, :ok, :ok] ## Note: In binding sections, you can filter by pattern-matching. # Bit comprehensions pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>> for <<r::8, g::8, b::8 <- pixels>>, do: {r, g, b} # => [{213,45,132},{64,76,32},{76,0,0},{234,32,15}] # Collect result to the stdio stream(echo program) stream = IO.stream(:stdio, :line) for line <- stream, into: stream do "#{line}\n" end
  31. Rest Contents • This slides don’t include some specific contents:

    • Concrete modules like Enum, Stream, IO, File • Structs …like Maps but more robust. • Module Attributes(written like @foo) • Type Specificaton …via module attribute.