Introducing Elixir

Introducing Elixir

Alexei Sholik

August 3, 2013 @ kievfprog.net

What is Elixir?

What is Elixir?

Erlang VM

What is Elixir?

Less code

What is Elixir?

More fun

In a nutshell

Erlang VM


             +--------+   +--------+
             | Erlang |   | Elixir |
             +--------+   +--------+
                 ||           ||
                 \/           \/
               +-----------------+
               | .beam byte code |
               +-----------------+
                       ||
                       \/
          +---------------------------+
          | BEAM emulator (Erlang VM) |
          +---------------------------+
        
        

Erlang VM

Why Elixir?

Elixir
==
PRODUCTIVITY

Why Elixir?

Elixir
==
FUN

Demo time!

Demo
recap

Mix: your new project manager

defmodule Fprog.Mixfile do
  use Mix.Project

  def project do
    [app: :fprog, deps: deps, ...]
  end

  def application do
    [applications: [:httpotion]]
  end

  defp deps do
    [{ :httpotion, github: "myfreeweb/httpotion" },
     { :jazz, github: "meh/jazz" }]
  end
end

jazz: simple API

defprotocol JSON.Decoder do
  def from_json(data)
end

defprotocol JSON.Encoder do
  def to_json(self, options)
end

JSON.encode!(dict / list / record)
JSON.decode!(json)
        

jazz: extensible API

defimpl JSON.Encoder, for: anything do
  def to_json(...), do: ...
end

defimpl JSON.Decoder, for: anything do
  def from_json(...), do: ...
end

JSON.encode!(anything)
JSON.decode!(json, as: anything)
        

What is Elixir
good for?

What is Elixir good for?

Web apps

What is Elixir good for?

DSLs

...and more

Everything Erlang can do, Elixir can do too

Who is using Elixir?

Who is using Elixir?

Development status

Development status

Getting started

Thank you!

Alexei Sholik

@true_droid
github.com/alco
        

elixir-lang.org | tryelixir.org

Random stuff

Pipe operator

From Programming Elixir by Dave Thomas

Enum and Stream

alias Stream, as: S ;  alias Enum, as: E

1..10 |> S.map(to_binary &1) |> E.each(IO.puts &1)
#=> prints numbers from 1 to 10

S.cycle([1, 2, 3]) |> S.map(&1 * &1) |> E.take(10)
#=> [1, 4, 9, 1, 4, 9, 1, 4, 9, 1]

{0, 1}
|> S.iterate(fn {a, b} -> {b, a + b} end)
|> S.map(elem &1, 0)
|> E.take(10)
#=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Pattern matching (1)

a = 1  #=> 1
1 = a  #=> 1

[a | b] = [1, 2, 3]
# a == 1
# b == [2, 3]

{ :event, _ } = { :event, "kievfprog" }  # OK
{ :event, _ } = { :error, "no event" }
#=> ** (MatchError) no match of right hand side
#                   value: {:error, "no event"}

Pattern matching (2)

<< a::utf8, _::binary >> = "ßtring"
# a == 223
# <<a>> == <<223>>

{ <<a::utf8>>, "\x{df}" }  # 0xDF == 223
#=> {"ß", "ß"}

binary_to_list "ß"
#=> [195, 159]

Pattern matching (3)

defmodule M do
  def test([_|_]), do: "list"
  def test([]),    do: "empty list"

  def test({ _, _ }), do: "a pair"

  def test(1234),  do: "one two three four"
  def test(x) when is_number(x),
                   do: "some other number"

  def test(_),     do: "something else"
end

Docstrings

@moduledoc %B"""
## String and binary operations

The functions in this module act according to the
Unicode Standard, version 6.2.0.
"""

@doc """
Convert all characters in the string to uppercase.
"""
@spec upcase(t) :: t
defdelegate upcase(binary), to: String.Unicode

@doc """
Convert all characters in the given string
to uppercase.

## Examples

    iex> String.upcase("abcd")
    "ABCD"

"""
@spec upcase(t) :: t
defdelegate upcase(binary), to: String.Unicode

Sigils

# %b, %B -- strings
IO.puts %B"hello \"name\""
#=> hello \"name\"

IO.puts %b/hello "name"/
#=> hello "name"

# %r, %R -- regular expressions
"aaab" =~ %r"a+b"  #=> true

# in the shell
iex> h Kernel.sigil_r

Function currying

Enum.all? [:a, :b, :c], &is_atom(&1)
#=> true

Enum.map  ["a", "B", "c"], &String.upcase &1
#=> ["A", "B", "C"]

Enum.sort [1, 2, 3], &( &2 < &1 )
#=> [3, 2, 1]

fun = &(&1 + &2 + &3)
fun.(1, 2, 3)
#=> 6

REPL

Nodes and binaries


# Node.list
# Node.connect
# a = "Hello, b!"
# Node.spawn :"...", fn -> ... end
#    IO.puts a <> " My name is #{Node.self}"

# :code.load_binary M, 'file', code