添加時間: 2016-04-30
html
def background_check(%{manager: employee} = company) do %{name: full_name} = employee from(c in Criminals, where: c.full_name == ^full_name, select: c) |> Repo.one |> case do nil -> congratulate(employee) criminal -> notify(company) end end
對參數 company
進行匹配, 析構出其中的 manager
字段git
對 manager
再次析構出其中的 name
字段github
而後查詢 Criminals
表進行對比shell
在單個表達式中一次匹配app
def check_company(%{manager: %{name: full_name} = employee} = company) do from(c in Criminals, where: c.full_name == ^full_name, select: c) |> Repo.one() |> case do nil -> congratulate(employee) criminal -> notify(company) end end
添加時間: 2016-04-18
ide
** (ExUnit.TimeoutError) test timed out after 60000ms. You can change the timeout: 1. per test by setting "@tag timeout: x" 2. per case by setting "@moduletag timeout: x" 3. globally via "ExUnit.start(timeout: x)" configuration 4. or set it to infinity per run by calling "mix test --trace" (useful when using IEx.pry) Timeouts are given as integers in milliseconds.
上面是一個超時的錯誤提示, 經過上面的描述, 咱們能夠很清楚的瞭解如何設置單元測試的超時, 對於須要長時間運行的測試, 請把timeout
設置的更大一點.函數
上面的說明標號分別爲工具
單獨設置一個測試@tag timeout: x
單元測試
整個測試用例@moduletag timeout: x
測試
全局設置ExUnit.start(timeout: x)
第四個不常見, 有空再研究一下.
添加時間: 2016-04-18
進程狀態能夠在任什麼時候候獲取和替換, 通常用於熱更的時候.
# 建立一個GenServer模塊 iex(1)> defmodule Test do ...(1)> use GenServer ...(1)> end {:module, Test, <<70, 79, 82, 49, 0, 0, 10, 40, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 2, 60, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>, :ok} # 啓動進程 iex(2)> GenServer.start_link Test, %{name: "developerworks"}, name: :server {:ok, #PID<0.72.0>} # 獲取進程狀態 iex(3)> :sys.get_state :server %{name: "developerworks"} # 替換狀態 iex(4)> :sys.replace_state :server, fn(state)-> %{name: "new_state"} end %{name: "new_state"} # 新狀態 iex(5)> :sys.get_state :server %{name: "new_state"}
http://www.hoterran.info/erlang-otp-sys-sourcecode
http://stackoverflow.com/questions/1840717/achieving-code-swapping-in-erlangs-gen-server
||
,&&
和!
兩邊支持任何數據類型and
, or
, not
第一個參數必須爲布爾類型
添加時間: 2016-04-06
二進制: 前綴0b
, 例如:
0b100000000 # 256
八進制: 前綴0o
, 例如:
0o400 # 256
十六進制: 前綴0x
, 例如:
0xFF # 255
添加時間: 2016-04-05
keywords = [a: 1, b: 2] Enum.into(keywords, %{})
iex(1)> keywords = [a: 1, b: 2] [a: 1, b: 2] iex(2)> Enum.into(keywords, %{}) %{a: 1, b: 2} iex(3)> map = Enum.into(keywords, %{}) %{a: 1, b: 2} iex(4)> map[:a] 1 iex(5)> map.a 1 # 動態訪問 iex(6)> map[:c] nil # 嚴格語法 iex(7)> map.c ** (KeyError) key :c not found in: %{a: 1, b: 2}
若是Key不存在, 嚴格語法拋出KeyError
異常, 動態訪問方式返回nil
, 能夠參考Jose Valim
的這篇文章Writing assertive code with Elixir
添加時間: 2016-04-05
對於ExUnit測試, 用.exs
文件, 所以不須要在每次修改的時候從新編譯. 若是編寫腳本或測試, 使用.exs
文件, 不然使用.ex
後綴.
解釋代碼須要消耗更多的時間來執行(解析, tokenize等), 但不要求編譯. 若是靈活性比執行速度更重要, 使用.exs
後綴, 不然使用.ex
.
添加時間: 2016-04-05
Elixir 的IEx默認是不帶歷史命令支持的, 退出Erlang VM後,以前的命令所有麼有了, 要跨多個IEx Session保存命令歷史, 可使用下面這個開源的工具:
git clone https://github.com/ferd/erlang-history.git cd erlang-history make install
安裝完成後啓動IEx就可使用了.
這裏還有一篇文章 Erlang 和 Elixir shell 歷史記錄設置
添加時間: 2016-04-02
建立一個工具模塊包括經常使用的輔助函數
defmodule Util do @mdoc """ 工具模塊 """ @doc """ 用於獲取UNIX時間戳 """ def get_unixtime() do {megas, secs, _micros} = :os.timestamp megas * 1000 * 1000 + secs end end
定義一個User
類型模塊
defmodule User do @mdoc """ 用戶類型 """ defstruct username: "", tel: "", email: "", created_at: Util.get_unixtime @type t :: %__MODULE__{ username: String.t, tel: String.t, email: String.t, created_at: Integer.t } end
測試代碼
# 測試 require Logger defmodule UserTest do def main() do # 建立一個新的User結構類型 user = %User{} # 打印 Logger.info "#{inspect user}" end end # 調用 UserTest.main
打開 warnings_as_errors
編譯器選項, 讓你的代碼沒有警告, 在config.exs
中設置編譯選項
Code.compiler_options([ debug_info: true, docs: true, ignore_module_conflict: false, warnings_as_errors: true ])
當心使用Enum.map/2
在集合過大的時候不要直接使用該函數, 請使用 Stream
模塊, 要獲取結果的時候再用 Enum
模塊中的函數計算最終結果.
http://elixir-lang.org/docs/stable/elixir/Kernel.SpecialForms.html#for/1
pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>> rgb = for <<r::8, g::8, b::8 <- pixels >> do {r, g, b} end IO.inspect rgb
for <<c <- " hello world ">>, c != ?\s, into: "", do: <<c>> "helloworld"
動態定義
經過函數名稱列表, 動態的建立函數的定義.
這種技巧一般用於批量的定義相似的函數通常參數數量相同, 函數名稱有規律的重複, 多用於開發API模塊
defmodule Reader do [:doc, :voice, :video] |> Enum.each(fn(name)-> def unquote(:"read_#{name}")(id) do IO.inspect("Call function #{unquote(name)}(#{id})") end end) end Reader.read_doc 1 # Call function doc(1) Reader.read_video 2 # Call function doc(2) Reader.read_voice 3 # Call function doc(3)
動態調用
使用apply/3
動態調用模塊
defmodule RiakPoolEx.Handlers.MediaHandler do @mdoc """ You can call functions in the module liks this: Exmaples: alias RiakPoolEx.QueryHandler.MediaHandler MediaHandler.read_doc(1) MediaHandler.read_voice(2) MediaHandler.read_video(3) MediaHandler.read_picture(4) """ alias RiakPoolEx.QueryHandler [:doc, :voice, :video, :picture] |> Enum.each(fn(name)-> def unquote(:"read_#{name}")(id) do apply(RiakPoolEx.QueryHandler, unquote(:"read_#{name}", [id])) end end) end