@qhwa on
creator of
worked at Alibaba
now at Helijia.com
program happily
high productivity
high maintainability
amazing community
IO.puts "Hello, world!"list = [:this, "is", 1, "list"]
list ++ ["!"]
# => [:this, "is", 1, "list", "!"]
{:this, :is, 1, "tuple"} args = [{:timeout, 5000}, {:retry, false}]# equals to
args = [timeout: 5000, retry: false]# shortcut
# can be used as:
http(url, timeout: 5000, retry: false)cities = %{cd: "成都", hz: "杭州"}Map.get(cities, :cd)
#=> "成都"cities.cd
#=> "成都"double = fn (n) -> n * 2 enddouble.(11)
#=> 22triple = &(&1 * 3)triple.(11)
#=> 33defmodule Greet do def welcome do
"Welcome to RubyConfChina!"
end
endGreet.welcome # or Greet.welcome()
#=> "Welcome to RubyConfChina!"Alright, but Ruby already offers all of these...
iex> a = 1
1iex> a
1iex> 1 = a
1iex> 2 = a
** (MatchError) no match of right
hand side value: 1iex> 1 = 1
1iex> 2 = 1
** (MatchError) no match of right hand side value: 1iex> {x, y} = {100, 50}
{100, 50}iex> x
100iex> y
50iex> [1, 2, funny | tail] = [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]iex> funny
3iex> tail
[4, 5]iex> {:ok, f} = File.read("./mix.exs")
# if read successfully
{:ok, "..."}iex> {:ok, f} = File.read("NON_EXIST_FILE")
# oops
** (MatchError) no match of right hand side
value: {:error, :enoent}result = do_something()
case result do
{:ok, result} -> process(result)
{:error, reason} -> show_msg(reason)
enddefmodule Fibonacci do def fib(0), do: 0 def fib(1), do: 1 def fib(n) do
fib(n - 2) + fib(n - 1)
end
end def fib(n) when n > 1 do
fib(n - 2) + fib(n - 1)
endSuppose we are going to implement:
[1, 2, 4, 5, "hello", "world"]
[2, 1, 5, 4, "world", "hello"]
defmodule MyList do
def swap(list) do
_swap(list, [])
end defp _swap([], current) do
current
end defp _swap([a], current) do
current ++ [a]
end defp _swap([a, b | tail], current) do
_swap(tail, current ++ [b, a])
end
end
defmodule UsersController do
def register(conn, %{"agreed" => false}) do
msg = "Please agree to continue."
render(conn, "new.html", alert: msg)
end
def register(conn, params) do
create_user_in_db(params)
redirect_to_profile(conn)
end
endLogic branch
Logic trunk
your code = small isolated logic branches.
people = DB.find_customersorders = Orders.for_customers(people)tax = sales_tax(orders, 2013)filing = prepare_filing(tax)filing = prepare_filing(
sales_tax(
Orders.for_customers(
DB.find_customers
), 2013
)
)DB.find_customers |> Orders.for_customers |> sales_tax(2013) |> prepare_filing(1..10) |> Enum.map(&(&1 * &1)) |> Enum.filter(&(&1 < 40))#=> [1, 4, 9, 16, 25, 36]assert 1 == 2
1) test parse messages from ...
test/my_test.exs:5
Assertion with == failed
code: 1 == 2
lhs: 1
rhs: 2class Employee
def initialize(name, salary)
@name = name
@salary = salary
end def change_salary_by(amt)
@salary = @salary + amt
end def description
"#{@name} makes #{@salary}"
end
endbob = Employee.new("Bob", 10_000)
bob.change_salary(1000)puts bob.description # "Bob makes 11000" def change_salary_by(amt)
# make function pure by returning a new object
self.class.new(@name, @salary + amt)
endbob = Employee.new("Bob", 10_000)
bob = bob.change_salary_by(1000)defmodule Employee do defstruct name: nil, salary: 0 def change_salary_by(person, amt) do
Map.update(person, :salary, amt, &(&1 + amt))
end def description(person) do
"#{person.name} makes #{person.salary}"
end
end
%Employee{name: "Bob", salary: 10_000} |> Employee.description() |> Employee.change_salary_by(1000) |> IO.puts # "Bob makes 11000"Reuse your code without worrying.
Process
Process
1.spawn
2. wait (block)
2. send message
3. receive messages
defmodule SpawnExample do
def test do spawn(Greet, :hello, [self, "Billy"]) receive do
{:ok, msg} -> IO.puts msg
end
end
end
defmodule Greet do
def hello(from, who) do
send(from, {:ok, "Hello, #{who}!"})
end
end
iex> SpawnExample.test
Hello, Billy!
:okProcess
Process
1.spawn
2. wait (block)
2. send message
3. receive messages
[1, 2, 3, 4] |> Enum.map(&(&1 * &1))
#=> [1, 4, 9, 16]
# parallel mapping!
[1, 2, 3, 4] |> Pmap.map(&(&1 * &1))
#=> [1, 4, 9, 16]defmodule Pmap do
def map(collection, f) do
me = self
pids = collection
|> Enum.map(fn(element) ->
spawn_link(fn -> send(me, {self, f.(element)}) end)
end)
pids
|> Enum.map(fn(pid) ->
receive do
{^pid, result} -> result
end
end)
end
end
Processes share nothing.
Processes everywhere, services everywhere.