[Erlang 0112] Elixir Protocols

简介: Why Elixir        为什么要学习Elixir?答案很简单,为了更好的学习Erlang.这么无厘头的理由?      Erlang语法设计几乎没有考虑过取悦开发者,所以学习之初的门槛略高.


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<T>( this IEnumerable<T> 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大事记:

本文转自博客园坚强2002的博客,原文链接:

http://www.cnblogs.com/me-sa/p/Elixir-Protocols.html如需转载请自行联系原博主。

目录
相关文章
|
Shell Perl
erlang 小技巧总结
开一个页面总结一些erlang的使用技巧,随时添加新的技巧。
|
消息中间件 网络协议 Go
[Erlang 0123] Erlang EPMD
 epmd进程和Erlang节点进程如影随形,在Rabbitmq集群,Ejabberd集群,Couchbase集群产品文档中都会有相当多的内容讲epmd,epmd是什么呢?   epmd 是Erlang Port Mapper Daemon的缩写,全称足够明确表达它的功能了(相比之下,OTP就.
2004 0
|
测试技术 Shell 开发工具
|
编解码 计算机视觉 存储
|
JavaScript 前端开发 Java
|
网络协议 Shell Go