IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原][Erlang 0112] Elixir Protocols

    ligaorenvip发表于 2014-09-12 10:19:20
    love 0

    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).
    也就是说它使用了类似Clojure Protocol的机制实现多态,那我们先看看Clojure里面的Protocol是怎样的:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    (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#中可以找到形式上非常类似的东西,看一个例子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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(this IEnumerable items)
    {
    StringBuilder sb = new StringBuilder("Data:");
    foreach (var item in items)
    {
    sb.AppendFormat("{0}\n", item);
    }
    Console.WriteLine(sb.ToString());
    }
    }

      

    调用的代码:
    1
    2
    3
    4
    5
    6
    7
    8
    static void Main(string[] args)
    {
    12.Dump();
    (12.23).Dump();
    (new List<string>() { "123", "ok", "test" }).Dump<string>();
    Console.ReadLine();
    }

      

    这个在C#中被称为Extension Methods ,可以点击这里查看详细讲解:http://msdn.microsoft.com/en-us/library/bb383977.aspx

    Elixir Protocols

    下面,看看Elixir的Protocol,下面选取的例子来自Elixir中的chars.ex https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/string/chars.ex
    这个模块为大部分(有些数据类型不支持)数据类型增加了一个to_string的方法,首先定义了一个protocol:
    1
    2
    3
    defprotocol String.Chars do
    def to_string(thing)
    end
    定义了protocol之后,下面就要按照各种类型做首先,下面截取的代码是针对integer和float的处理:

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

     

    调用的时候,对于没有实现的情况
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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
    Protocol的代码实现在https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/protocol.ex 等我们完成了对Elixir宏的探索之后,再回来仔细看Protocol的实现.
    {ok,"今天先到这里"}
    最后小图一张,2013大事记:

      



沪ICP备19023445号-2号
友情链接