Elixir

Hal E. Fulton

the next

Ruby

?

Is

I wrote one of these books

Elixir

the next

Ruby

?

Is

What does that even mean?

Let's assume an answer of "Yes, maybe."

  • Ruby is going away. It isn't.
  • Ruby is useless. Not true.
  • You have to stop using Ruby. You don't.
  • I myself will stop using Ruby. Not true!

This doesn't mean:

But it does mean:

  • Elixir is more cutting edge. Ruby is not.
  • OOP is arguably dying. I said arguably, ok?
  • Elixir is far more suited to concurrency.
  • A lot of the smart, cool kids are picking up Elixir.
  • There are encouraging similarities in the communities.

I believe that Elixir

will surpass Ruby in popularity

within three years.

The Free Lunch Is Over

A Fundamental Turn Toward Concurrency in Software

Go read this article. No, really.

(Herb Sutter)

Similar communities?

  • A diverse, eclectic group
  • High energy and innovative people
  • Some of the same people: Dave Thomas,
    James Edward Grey, Jim Freeze, myself, others
  • Innovation not quite as cautious?
  • MINASWAN => JICASWAC
  • "José is chill and so we are chill"

Why Ruby?

  • Radically object-oriented
  • Beautiful syntax
  • Consistent semantics
  • Highly expressive
  • But... not very concurrent
  • And some say it is slow

Why Erlang?

  • Functional language
  • Good support for concurrency
  • BEAM
  • Small, fast, lightweight processes
  • OTP

"If somebody came to me and wanted to pay me a lot of money to build a large-scale message handling system that really had to be up all the time, could never afford to go down for years at a time, I would unhesitatingly choose Erlang to build it in."

Tim Bray

Sun Microsystems

Why not Erlang?

  • Ugly syntax?
  • Inconsistencies
  • Old-fashioned pieces
  • "Onions in the varnish"

Why Elixir?

  • Runs on BEAM
  • Compatible with Erlang
  • Can access OTP
  • Prettier syntax?
  • Modernized language features
  • Borrows from Ruby

Elixir...

  • Obviously borrows from Erlang
  • Also borrows from Ruby
  • Also innovates (borrows from elsewhere)

Erlang

Ruby

Elixir

Anonymous functions

  sum = &(&1 + &2)

  c = sum.(4,3)
  sum = fn(a, b) -> a + b end

  c = sum.(4, 3)

The "pipeline" operator

means

  filing = DB.find_customers 
   |> Orders.for_customers 
   |> sales_tax(2015) 
   |> prepare_filing 
  f(x,y)
  filing = prepare_filing(sales_tax(Orders.for_customers(DB.find_customers),2015)) 
people = DB.find_customers 
orders = Orders.for_customers(people) 
tax    = sales_tax(orders, 2015) 
filing = prepare_filing(tax) 
  x |> f(y)

But there's a better way...

  defmodule AnagramFinder do
    def search_file(file) do   
      get_words(file)
      |> process_all
      |> Enum.each &print_words/1  
    end
   
    defp process_all(list) do
      list 
      |> Enum.group_by(HashDict.new, 
                       &(Enum.sort(String.codepoints(&1)))) 
    end

    defp get_words(file) do
      File.read!(file)
      |> String.split("\n", trim: true)
    end

    defp print_words({_key, [_word]}), do: nil

    defp print_words({_key, words}) do
      [first | rest] = words 
      |> Enum.reverse
      IO.puts "#{first}: #{Enum.join(rest, ", ")}" 
    end
  end

  AnagramFinder.search_file("/usr/share/dict/words")

Anagram Finder in Elixir

Other features...

  • Multiple function heads
  • Guard clauses
  • Macros
  • Protocols
  • Streams
  • Tasks
  • Small, fast, lightweight processes
  • Process supervision

Multiple function heads

  defmodule Fibonacci do
    def fib(0), do: 1
    def fib(1), do: 1
    def fib(n), do: fib(n-2) + fib(n-1)
  end
  
  IO.puts Fibonacci.fib(5)     # 8
  IO.puts Fibonacci.fib(10)    # 89

Guard clauses

  # on a named function

  def circle_area(radius) when is_number(radius)
    3.1416 * radius * radius
  end


  # on an anonymous function

  func = fn 
           x when is_number(x) -> "a number"
           x when is_binary(x) -> "a binary"
           x -> "something else"
         end


Macros

  defmodule MyMacros do

    defmacro unless(test, expr) do
      quote do
        if(!unquote(test), do: unquote(expr))
      end 
    end

  end



  # in another context:

  require MyMacros

  unless 2 == 3, do: IO.puts "That's a relief."

Two observations...

Multiple function heads, pattern matching, and guard clauses can all help reduce branching logic.

Tail recursion makes it possible in many cases to reduce looping.

You can really

with just one loop

 

and one branch.

mess yourself up

Avoiding branches...

  defmodule Quadratic do
    def real_roots(a, b, c) when b*b - 4*a*c > 0,  do: 2
    def real_roots(a, b, c) when b*b - 4*a*c == 0, do: 1
    def real_roots(a, b, c) when b*b - 4*a*c < 0,  do: 0
  end

Avoiding loops...

  defmodule Multi do
  
    def print(1, str), do: IO.puts str 

    def print(n, str) do
      IO.puts str
      print(n-1, str)
    end

  end


  greeting = "Salve mundo!"

  Multi.print(5, greeting)

Where does this

ultimately lead?

Functional programming...

Lightweight processes...

Fast messaging...

Multiple processors/cores

Those who

dreamed

early...

What is "object-oriented" really?

"I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages. So messaging came at the very beginning -- it took a while to see how to do messaging in a programming language efficiently enough to be useful."

Alan Kay

"Can Programming Be Liberated
from the von Neumann Style?
A Functional Style
and Its Algebra of Programs"

Turing Award Lecture

of John Backus, 1978

The machine, as we envisioned it, would contain a million tiny computers, all connected by a communications network. We called it a "Connection Machine."

W. Daniel Hillis

"Richard Feynman and the Connection
Machine," Physics Today, 1989

But enough dreaming
 and back to reality...

Note: I'm working on a new book.

I hope you will buy it someday.

Questions?

Thank you!

Made with Slides.com