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!
Is Elixir the Next Ruby?
By hal_9000
Is Elixir the Next Ruby?
- 286