[Erlang 0112] Elixir Protocols
阿新 • • 發佈:2018-12-29
Why Elixir
為什麼要學習Elixir?答案很簡單,為了更好的學習Erlang.這麼無厘頭的理由?
Erlang語法設計幾乎沒有考慮過取悅開發者,所以學習之初的門檻略高.對於已經克服了最初語法障礙的同學,Elixir其實沒有什麼吸引力. 在Elixir之前已經有很多類似的專案,比如http://lfe.github.io Elixir類似思路的還有http://reia-lang.org 在前,但Elixir顯然做得更好一些.看這些語言的時候,會有一種感覺:把這語言語法層面做優化調整,理想狀態就是Erlang的樣子吧!
那為什麼要投入時間到Elixir? 深入Elixir內部,可以看到很多非常棒的設計,這些設計並不陌生,之前散見於各種開源專案.不過現在Elixir將這些解決方案整合在一起,而且更具有系統性.對我來說,這是一個很好的切入點.對於很多Ruby開發者來講,Elixir具有很強的語法親和力,而這點對我來講沒有什麼意義,其實我反倒覺得Elixir在語法層面複雜了很多,需要"記住"的規則比較多,而Erlang這方面要精簡很多.
多型
維基百科上對多型的定義 polymorphism is the provision of a single interface to entities of different types. [Link]對不同型別的資料實體提供一致的處理介面,對於這個定義有很多實現方式,比如介面,泛型.在Elixir提到多型的時候,是這樣描述的:Elixir also provides first-class support for pattern matching, polymorphism via protocols (similar to Clojure's), aliases and associative data structures (usually known as dicts or hashes in other programming languages).
(ns elixir-demo ) (defprotocol Concatenatable (cat [this other])) (extend-type java.util.List Concatenatable (cat [this other] (concat this other)) ) (extend-type String Concatenatable (cat [this other] (.concat this other)) ) (println (cat [1,2,3,4] [5,6,7])) (println (cat "Hello " "World!!!!" ))
(1 2 3 4 5 6 7) Hello World!!!! 這個,我們在C#中可以找到形式上非常類似的東西,看一個例子:
public static class TypeExtensions { public static void Dump(this int num) { Console.WriteLine(string.Format("The int number is :{0} \r\n ", num)); } public static void Dump(this double num) { Console.WriteLine(string.Format("The float number is :{0} \r\n ", num)); } public static void Dump<T>(this IEnumerable<T> items) { StringBuilder sb = new StringBuilder("Data:"); foreach (var item in items) { sb.AppendFormat("{0}\n", item); } Console.WriteLine(sb.ToString()); } }呼叫的程式碼:
static void Main(string[] args) { 12.Dump(); (12.23).Dump(); (new List<string>() { "123", "ok", "test" }).Dump<string>(); Console.ReadLine(); }
defprotocol String.Chars do def to_string(thing) end定義了protocol之後,下面就要按照各種型別做首先,下面擷取的程式碼是針對integer和float的處理:
defimpl String.Chars, for: Integer do def to_string(thing) do integer_to_binary(thing) end end defimpl String.Chars, for: Float do def to_string(thing) do iolist_to_binary(:io_lib_format.fwrite_g(thing)) end end呼叫的時候,對於沒有實現的情況
iex(8)> to_string([1,2]) <<1, 2>> iex(9)> to_string(:a) "a" iex(10)> to_string(12.3) "12.3" iex(11)> to_string(12) "12" iex(12)> to_string({1,2}) ** (Protocol.UndefinedError) protocol String.Chars not implemented for {1, 2} /data2/src_elixir/elixir/lib/elixir/lib/string/chars.ex:3: String.Chars.impl_for!/1 /data2/src_elixir/elixir/lib/elixir/lib/string/chars.ex:17: String.Chars.to_string/1可以限定的資料型別有:Record,Tuple,Atom,List,BitString,Integer,Float,Function,PID,Port,Reference,Any {ok,"今天先到這裡"} 最後小圖一張,2013大事記: