<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_回头再说  坚强2002的博客</title><subtitle type="text">在每个新的一年三百六十五天我们都每天进步一点点......</subtitle><id>http://feed.cnblogs.com/blog/u/20888/rss</id><updated>2012-06-04T08:15:52Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/20888/rss"/><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/31/erlang-unicode.html</id><title type="text">[Erlang 0062] Erlang Unicode 两三事</title><summary type="text">不少人和我一样在Erlang实践过程中都会遇到中文的问题,其中有中文显示的问题有正则表达式匹配的问题等等;今天请教立涛之后梳理了一下,整理于此.</summary><published>2012-05-31T14:55:00Z</published><updated>2012-05-31T14:55:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/31/erlang-unicode.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/31/erlang-unicode.html"/><content type="html">&lt;p&gt;&amp;nbsp;不少人和我一样在Erlang实践过程中都会遇到中文的问题,其中有中文显示的问题有正则表达式匹配的问题等等;今天请教立涛之后梳理了一下,整理于此.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;概念Unicode UTF-8&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 《深入理解计算机系统》里面提到过"信息=数据位+上下文",同样的数据在不同的上下文环境有不同的解读方式; 同样的二进制数据按照不同的编码规范去解析得出的结果也不尽相同,如果使用错误的编码方式去解读数据就会出现所谓的乱码问题.看看下面的例子:&amp;lt;&amp;lt;123,231&amp;gt;&amp;gt;.可以被输出为可打印字符{?,也可以按照不同的数据位规则进行分割.可以看到不同规则下,解读出来的变量值是完全不同的.&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.8.2  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; &amp;lt;&amp;lt;123,231&amp;gt;&amp;gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"{?&amp;gt;&amp;gt;&lt;br/&gt;2&amp;gt; &amp;lt;&amp;lt;A:1,B:7,C:8&amp;gt;&amp;gt; = v(1&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"{?&amp;gt;&amp;gt;&lt;br/&gt;3&amp;gt;&lt;span style="color: #000000;"&gt; b().&lt;br/&gt;A &lt;/span&gt;= 0&lt;span style="color: #000000;"&gt;&lt;br/&gt;B &lt;/span&gt;= 123&lt;span style="color: #000000;"&gt;&lt;br/&gt;C &lt;/span&gt;= 231&lt;span style="color: #000000;"&gt;&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;4&amp;gt; &amp;lt;&amp;lt;D:5,E:3,F:7,G:1&amp;gt;&amp;gt; = v(1&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"{?&amp;gt;&amp;gt;&lt;br/&gt;5&amp;gt;&lt;span style="color: #000000;"&gt; b().&lt;br/&gt;A &lt;/span&gt;= 0&lt;span style="color: #000000;"&gt;&lt;br/&gt;B &lt;/span&gt;= 123&lt;span style="color: #000000;"&gt;&lt;br/&gt;C &lt;/span&gt;= 231&lt;span style="color: #000000;"&gt;&lt;br/&gt;D &lt;/span&gt;= 15&lt;span style="color: #000000;"&gt;&lt;br/&gt;E &lt;/span&gt;= 3&lt;span style="color: #000000;"&gt;&lt;br/&gt;F &lt;/span&gt;= 115&lt;span style="color: #000000;"&gt;&lt;br/&gt;G &lt;/span&gt;= 1&lt;span style="color: #000000;"&gt;&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;6&amp;gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;数字123,231在EShell中输出为字符"{?",也就是数字和字符之间有对应关系,这就是编码.所谓编码就是定义了字符和数字之间的对应关系,比如ASCII编码中a字符对应数值97;在ASCII字符集中就不包含中文字符和数值之间的对应关系; 一个理想的解决方案就是采用一种统一的编码规范.Unicode就为解决这个问题而生,Unicode编码用以统一地体现和处理世界上大部分的文字系统,并为其编码,在Unicode相关资料中频繁出现的名词codepoint实际上就是数字;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;Unicode编码系统包含两部分的内容:编码方式和实现方式.Unicode会使用几个字节表示字符呢?这属于实现方式(或者说表达方式),Unicode只规定符号的编码,不规定如何表达.一个字符的Unicode编码是确定的,但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同.Unicode的实现方式称为Unicode转换格式(Unicode Transformation Format,简称为UTF),UTF-8就是转换格式之一.UTF-8采用变长字节存储Unicode,如果一个仅包含基本7位ASCII字符的Unicode文件,如果每个字符都使用2字节的原Unicode编码传输,其第一字节的8位始终为0.这就造成了比较大的浪费,对于这种情况可以使用UTF-8编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0).而遇到与其他Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别.这样对以7位ASCII字符为主的西文文档就大大节省了编码长度.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;一个字符的用两个字节表示16位的编码空间,也就是每个字符占用2个字节.理论换上有65535个字符,实际应用中并没有完全使用这16位编码,而是保留了大量空间作为特殊使用或者扩展,比如 16#D800 - 16#DFFF 就是保留区域;其中16#FEFF被用作BOM(byte-order mark)即字节顺序记号,不建议在其它场景使用.&lt;br /&gt;    维基百科:Unicode 编码：http://zh.wikipedia.org/wiki/Unicode &amp;nbsp;UTF-8编码：http://zh.wikipedia.org/wiki/UTF-8&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;&lt;span&gt;Erlang &amp;amp; Unicode&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; Erlang的string实际上就是整数项组成的list,注意string的编解码使用是使用ISO-latin-1字符集,即:每8字节当成一个整体进行解读;这个字符集是Unicode的子集.Erlang list编解码很容易扩展到整个unicode编码:由于编码是整数和字符的对应关系,只要list中的整函数是有效的Unicode codepoint就可以找到对应的字符;二进制数据处理起来就麻烦一些了,二进制数据是紧凑排列的:一个字节代表一个字符,而不是两个字(word)一个字符,这里如果存在疑问可以查看erlang官方文档中关于内存消耗的列表:&lt;/span&gt;&lt;span&gt;&lt;a href="http://www.erlang.org/doc/efficiency_guide/advanced.html"&gt;http://www.erlang.org/doc/efficiency_guide/advanced.html&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;.平时我们使用的erlang:list_to_binary,常规的Erlang string(ISO-latin编码的string)可以逐字节逐字符顺利转成binary.但是超出ISO-latin编码范围就会出错了,看下面的例子:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; L=[10,12,23,45&lt;span style="color: #000000;"&gt;].&lt;br/&gt;[&lt;/span&gt;10,12,23,45&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;2&amp;gt;&lt;span style="color: #000000;"&gt; list_to_binary(L).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;10,12,23,45&amp;gt;&amp;gt;&lt;br/&gt;3&amp;gt; L2= "中国"&lt;span style="color: #000000;"&gt;.      &lt;br/&gt;[&lt;/span&gt;20013,22269&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;4&amp;gt;&lt;span style="color: #000000;"&gt; list_to_binary(L2).&lt;br/&gt;&lt;/span&gt;**&lt;span style="color: #000000;"&gt; exception error: bad argument&lt;br/&gt;     in function  list_to_binary&lt;/span&gt;/1&lt;span style="color: #000000;"&gt;&lt;br/&gt;        called as list_to_binary([&lt;/span&gt;20013,22269&lt;span style="color: #000000;"&gt;])&lt;br/&gt;&lt;/span&gt;5&amp;gt;&lt;span style="color: #000000;"&gt; unicode:characters_to_list(L2).&lt;br/&gt;[&lt;/span&gt;20013,22269&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;6&amp;gt; unicode:characters_to_binary(L2). &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;注意"中国"用二进制占用了6个字节&lt;/span&gt;&lt;br/&gt;&amp;lt;&amp;lt;228,184,173,229,155,189&amp;gt;&amp;gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;之前我在&lt;a href="http://www.cnblogs.com/me-sa/archive/2011/12/25/erlang0024.html" target="_blank"&gt;[Erlang 0024]Erlang二进制数据处理&lt;/a&gt; 的时候提到过,UTF-8是Erlang二进制处理的标准编码形式,一旦出现需要处理Unicode二进制数据的场景,默认就会选择UTF8编码.比特语法支持使用其它的编解码方式,但是erlang类库中处理二进制都是使用UTF-8编码.字符串可以接受Unicode字符,但是Erlang的语言元素编写还是限制在ISO-latin-1的范围内.Erlang编译过程依然是使用ISO-latin-1编码,这样的影响是什么呢?代码中出现的Unicode字符会有部分无法在ISO-latin-1找到对应的字符,那怎么办呢?没关系,找不到对应的字符就按照整形数去处理就好了.&lt;/p&gt;&lt;p&gt;&amp;nbsp; Erlang Shell对unicode的支持要强一些,但是也并不完善,下面我们通过一系列实验来看上面的问题,在test模块里面我们准备两条测试数据:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;data()-&amp;gt;&lt;br/&gt;   "hello 中国 ren"&lt;span style="color: #000000;"&gt;.&lt;br/&gt;data2()&lt;/span&gt;-&amp;gt;&lt;br/&gt;   &amp;lt;&amp;lt;"hello 中国 ren"&amp;gt;&amp;gt;.&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;启动Erlang Shell,我们对比一下数据之间的差异:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; "hello 中国 ren".  &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;在shell中输入包含中文的string,可以看到它就是一个List,注意中文字符对应的数值&lt;/span&gt;&lt;br/&gt;[104,101,108,108,111,32,20013,22269,32,114,101,110&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;2&amp;gt; test:data().        &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;注意下面的数据,中文部分数值已经被切割成两组数据&lt;/span&gt;&lt;br/&gt;[104,101,108,108,111,32,228,184,173,229,155,189,32,114,101&lt;span style="color: #000000;"&gt;,&lt;br/&gt;&lt;/span&gt;110&lt;span style="color: #000000;"&gt;]   &lt;br/&gt;&lt;/span&gt;3&amp;gt; &amp;lt;&amp;lt;"hello 中国 ren"&amp;gt;&amp;gt;.  &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;而这样的数据在shell中直接出错了 (注意:windows下可能是正常的)&lt;/span&gt;&lt;br/&gt;**&lt;span style="color: #000000;"&gt; exception error: bad argument&lt;br/&gt;&lt;/span&gt;4&amp;gt; test:data2().   &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;看看这里二进制的输出,数值上是和v(2)的数值上是一致的&lt;/span&gt;&lt;br/&gt;&amp;lt;&amp;lt;104,101,108,108,111,32,228,184,173,229,155,189,32,114&lt;span style="color: #000000;"&gt;,&lt;br/&gt;  &lt;/span&gt;101,110&amp;gt;&amp;gt;&lt;br/&gt;5&amp;gt; unicode:characters_to_binary(v(1)).  &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;把v(1)的结果转成二进制,为什么不用list_to_binary?往下看&lt;/span&gt;&lt;br/&gt;&amp;lt;&amp;lt;104,101,108,108,111,32,228,184,173,229,155,189,32,114&lt;span style="color: #000000;"&gt;,&lt;br/&gt;  &lt;/span&gt;101,110&amp;gt;&amp;gt;&lt;br/&gt;6&amp;gt; io:format("~ts~n",[v(1)]). &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;注意这里格式化的时候使用的修饰符是~ts&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;hello 中国 ren&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;7&amp;gt; io:format("~ts~n",[v(2)]).  &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;v(2)输出的内容并不是我们期望的                       &lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;hello &amp;auml;&amp;cedil;&amp;shy;&amp;aring;&amp;frac12; ren&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;8&amp;gt; io:getopts().  &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;是不是觉得少检查了点什么?是的 看看环境编码&lt;/span&gt;&lt;br/&gt;[{expand_fun,#Fun&amp;lt;group.0.33302583&amp;gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{echo,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{binary,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{encoding,unicode}]&lt;br/&gt;&lt;/span&gt;9&amp;gt; list_to_binary(v(1)). &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;看到了吧,这样会异常的&lt;/span&gt;&lt;br/&gt;**&lt;span style="color: #000000;"&gt; exception error: bad argument&lt;br/&gt;     in function  list_to_binary&lt;/span&gt;/1&lt;span style="color: #000000;"&gt;&lt;br/&gt;        called as list_to_binary([&lt;/span&gt;104,101,108,108,111,32,20013,22269,32,114,101,110&lt;span style="color: #000000;"&gt;])&lt;br/&gt;&lt;/span&gt;10&amp;gt; list_to_binary(v(2&lt;span style="color: #000000;"&gt;)).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;104,101,108,108,111,32,228,184,173,229,155,189,32,114&lt;span style="color: #000000;"&gt;,&lt;br/&gt;  &lt;/span&gt;101,110&amp;gt;&amp;gt;&lt;br/&gt;14&amp;gt; &lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;进行到这里,下面这个问题就有答案了,我们在Shell中执行下面的语句:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;14&amp;gt;  re:run("hello 中国 ren", "[\x{4e00}-\x{9fff}]+"&lt;span style="color: #000000;"&gt;, [unicode]).&lt;br/&gt;{match,[{&lt;/span&gt;6,6&lt;span style="color: #000000;"&gt;}]}&lt;br/&gt;&lt;/span&gt;15&amp;gt;&lt;span style="color: #000000;"&gt; &lt;br/&gt;然后我们把这条语句放在模块代码中执行:&lt;br/&gt;re() &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;   re:run(&lt;/span&gt;"hello 中国 ren", "[\x{4e00}-\x{9fff}]+"&lt;span style="color: #000000;"&gt;, [unicode]).&lt;br/&gt;执行结果:&lt;br/&gt;&lt;/span&gt;15&amp;gt;&lt;span style="color: #000000;"&gt; test:re().&lt;br/&gt;nomatch&lt;br/&gt;&lt;/span&gt;16&amp;gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;答案就是:在模块文件进行编译的时候使用的是ISO-latin-1,其中的中文并不在其字符集中,所以转成了两组数字!被转成两组数字之后,也就无法被正则表达式命中了.而在Erlang Shell中,中文字符可以被正确编码,所以会被正则命中.而仔细关注一下正则表达式,其实就是大致上覆盖了中文字符在unicode字符集中对应的数值区间.&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &amp;nbsp;对于这种情况只要让unicode避开编译阶段就可以了,比如把这类文本放在外部文本中,下面立涛给的这份代码样例中演示了从外部文件读取文本内容,并匹配中文. https://gist.github.com/2768621 &lt;br /&gt;&amp;nbsp; &amp;nbsp;方法二:在源代码中使用Unicode有一个语法糖可以用 \x{400} 的形式:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;3&amp;gt; $\x{400&lt;span style="color: #000000;"&gt;}.&lt;br/&gt;&lt;/span&gt;1024&lt;br/&gt;4&amp;gt; 16#400&lt;span style="color: #000000;"&gt;.&lt;br/&gt;&lt;/span&gt;1024&lt;br/&gt;5&amp;gt;  erl_scan:string("\"\x{400}\"."&lt;span style="color: #000000;"&gt;).&lt;br/&gt;{ok,[{&lt;/span&gt;'[',1},{integer,1,1024},{']',1},{dot,1}],1&lt;span style="color: #000000;"&gt;}&lt;br/&gt;&lt;/span&gt;6&amp;gt;  erl_scan:string("\"16#400\"."&lt;span style="color: #000000;"&gt;).&lt;br/&gt;{ok,[{string,&lt;/span&gt;1,"16#400"},{dot,1}],1}&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; 注意正则表达式中\x{4e00}就使用了这样的表达方式&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; "中国"&lt;span style="color: #000000;"&gt;.&lt;br/&gt;[&lt;/span&gt;20013,22269&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;2&amp;gt; integer_to_list(20013,16&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;"4E2D"&lt;br/&gt;3&amp;gt; $\x{4E2D&lt;span style="color: #000000;"&gt;}.&lt;br/&gt;&lt;/span&gt;20013&lt;br/&gt;4&amp;gt; list_to_binary([20013&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;&lt;/span&gt;**&lt;span style="color: #000000;"&gt; exception error: bad argument&lt;br/&gt;     in function  list_to_binary&lt;/span&gt;/1&lt;span style="color: #000000;"&gt;&lt;br/&gt;        called as list_to_binary([&lt;/span&gt;20013&lt;span style="color: #000000;"&gt;])&lt;br/&gt;&lt;/span&gt;5&amp;gt; unicode:charaters_to_binary([20013&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;&lt;/span&gt;** exception error: undefined function unicode:charaters_to_binary/1&lt;br/&gt;6&amp;gt; unicode:characters_to_binary([20013&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"&amp;auml;&amp;cedil;&amp;shy;"&amp;gt;&amp;gt;&lt;br/&gt;7&amp;gt;&lt;span style="color: #000000;"&gt; io:getopts().&lt;br/&gt;[{expand_fun,#Fun&lt;/span&gt;&amp;lt;group.0.33302583&amp;gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{echo,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{binary,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{encoding,unicode}]&lt;br/&gt;&lt;/span&gt;8&amp;gt; &lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;一个细节"~ts" 修饰符&lt;/strong&gt;&lt;br /&gt;The Erlang compiler will interpret the code as ISO-8859-1 encoded text, which limits you to Latin characters."translation modifier" when working with Unicode texts. The modifier is "t". When applied to the "s" control character in a formatting string, it accepts all Unicode codepoints and expect binaries to be in UTF-8.&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; io:format("~ts",[unicode:characters_to_binary([20013&lt;span style="color: #000000;"&gt;])]).&lt;br/&gt;中ok&lt;br/&gt;&lt;/span&gt;2&amp;gt; io:format("~ts",[unicode:characters_to_binary([20013,22269&lt;span style="color: #000000;"&gt;])]).&lt;br/&gt;中国ok&lt;br/&gt;&lt;/span&gt;3&amp;gt;  L=[229,136,157,231,186,167], io:format("~ts"&lt;span style="color: #000000;"&gt;, [list_to_binary(L)]).             &lt;br/&gt;初级ok&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;unicode &amp;amp; mochiwebuft8&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;Erlang unicode模块提供了基本的转换功能,上面的测试代码中已经有应用,该模块暴露出来的方法有:characters_to_list/1,2&amp;nbsp;characters_to_binary/1,2,3&amp;nbsp;bom_to_encoding/1&amp;nbsp;encoding_to_bom/1;mochiwebuft8中提供了专门的模块,方便处理UTF8相关的转换,看下例子:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; mochiutf8:codepoint_to_bytes(20320&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"&amp;auml;&amp;frac12; "&amp;gt;&amp;gt;&lt;br/&gt;2&amp;gt; io:format("~ts",[v(1&lt;span style="color: #000000;"&gt;)]).&lt;br/&gt;你ok&lt;br/&gt;&lt;/span&gt;3&amp;gt; mochiutf8:codepoint_to_bytes(22909&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"&amp;aring;&amp;yen;&amp;frac12;"&amp;gt;&amp;gt;&lt;br/&gt;4&amp;gt; io:format("~ts",[v(3&lt;span style="color: #000000;"&gt;)]).           &lt;br/&gt;好ok&lt;br/&gt;&lt;/span&gt;5&amp;gt; mochiutf8:codepoint_to_bytes([20320,22909&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;&lt;/span&gt;** exception error: no function clause matching mochiutf8:codepoint_to_bytes([20320,22909]) (src/mochiutf8.erl, line 20&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;6&amp;gt; mochiutf8:codepoints_to_bytes([20320,22909&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;&lt;/span&gt;&amp;lt;&amp;lt;"&amp;auml;&amp;frac12; &amp;aring;&amp;yen;&amp;frac12;"&amp;gt;&amp;gt;&lt;br/&gt;7&amp;gt; io:format("~ts",[v(6&lt;span style="color: #000000;"&gt;)]).                    &lt;br/&gt;你好ok&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;最后:Windows下不省心啊&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在官方文档中,对于windows环境中Erlang shell的描述是"The interactive Erlang shell, when started towards a terminal or started using the werl command on windows, can support Unicode input and output."即:如果是在windows中启动werl可以支持Unicode的输入输出,&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; "国家"&lt;span style="color: #000000;"&gt;.&lt;br/&gt;[&lt;/span&gt;22269,23478&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;2&amp;gt; io:format("~p~n",["国家"&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;[&lt;/span&gt;22269,23478&lt;span style="color: #000000;"&gt;]&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;3&amp;gt; io:format("~w~n",["国家"&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;[&lt;/span&gt;22269,23478&lt;span style="color: #000000;"&gt;]&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;4&amp;gt;&lt;br/&gt;4&amp;gt; io:format("~ts~n",["国家"&lt;span style="color: #000000;"&gt;]).&lt;br/&gt;国家&lt;br/&gt;ok&lt;br/&gt;&lt;/span&gt;5&amp;gt;&lt;br/&gt;5&amp;gt; lists:keyfind(encoding,1&lt;span style="color: #000000;"&gt;,io:getopts()).&lt;br/&gt;{encoding,unicode}&lt;br/&gt;&lt;/span&gt;6&amp;gt; &lt;/div&gt;&lt;p&gt;类似的代码在Centos中执行:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;同样的代码在Centos中:&lt;br/&gt;Eshell V5.&lt;/span&gt;9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; "你好"&lt;span style="color: #000000;"&gt;.&lt;br/&gt;[&lt;/span&gt;20320,22909&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;2&amp;gt; list_to_binary(v(1&lt;span style="color: #000000;"&gt;)).&lt;br/&gt;&lt;/span&gt;**&lt;span style="color: #000000;"&gt; exception error: bad argument&lt;br/&gt;     in function  list_to_binary&lt;/span&gt;/1&lt;span style="color: #000000;"&gt;&lt;br/&gt;        called as list_to_binary([&lt;/span&gt;20320,22909&lt;span style="color: #000000;"&gt;])&lt;br/&gt;&lt;/span&gt;3&amp;gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;貌似,在windows中unicode的问题解决的看上去很美啊,好吧,看下面的这张图:&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012053122513394.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;2012-6-1 12:09:49更新: 关于上面的截图,我还是误解了,看下面的讨论&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770) 11:45:04&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;Shell &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;在 unicode 环境下，中文会被编译为 [20013,22269,20154] 这样的双字节数字，&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;在 latin1 环境下，中文会被编译为 [228,184,173,229,155,189,228,186,186] 这样的单字节数字，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;所以在 unicode 环境下需要用 [\x{4e00}-\x{9fff}] 来匹配，是双字节的表达式，&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;latin 环境下需要用 [\x81-\xfe][\x40-\xfe] 来匹配，是单字节的表达式。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;然后 windows 下面，cmd 默认是 latin1 环境，werl.exe 默认是 unicode 环境。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:47:01&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;windows 的默认字符集是各国的本地语言，像中文是 GBK ，都会被 erlang 视为 latin1 环境。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:47:58&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;windows里面的事情就诡异了 看上面的截图&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:48:11&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;然后在 unicode 环境下，不能用 list_to_binary 来转换 unicode 字符，&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;要用 list_to_binary(unicode:character_to_list())&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;doc 里面的 unicode 文档讲了这个问题。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:49:14&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #c0c0c0;"&gt;深圳-燕尘(6108770)  11:45:04&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;在 unicode 环境下，中文会被编译为 [20013,22269,20154] 这样的双字节数字，&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;在 latin1 环境下，中文会被编译为 [228,184,173,229,155,189,228,186,186] 这样的单字节数字&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;这个是在shell还是在module?&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:50:05&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;shell&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;在 module 环境下，估计是会跟文件的编码有关。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:51:34&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;shell中这样说是对的 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;深圳-燕尘(6108770)  11:51:58&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;我用的默认 ANSI 格式保存，所以无论在 unicode 或者在 latin1 的 shell 下调用，它们都能正确运行。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:52:40&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;我们都是使用UTF-8&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:52:46&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;如果文件是 UTF-8 格式，估计就会把中文给编译成 双字节的数字了。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;就是这样，如果实在 Module 里用，跟你的文件编码相关，挑选不同的表达式。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;你自己测试测试好了，另存为 ANSI 看看&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:54:14&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;调用 MODULE 的时候，结果跟 shell 的语言环境无关。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:54:53&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;不会的 和文件编码没有关系 erlang编译器编译的时候使用latin编码 中文会编译成单字节数字&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;广州-ErLang低手(119684825)  11:55:21&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;那就好&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;呵呵&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:55:48&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;测试测试啊&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;深圳-燕尘(6108770)  11:57:06&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;哟，我测试了。不管文件是啥编码，latin1 那个表达式都能用&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:57:21&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;是的&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:58:39&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;不去管windows下的怪异情况 一切都能理顺了&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:59:16&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;无论shell是什么字符集，结果都是能匹配：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;但是可以从匹配的位置看到，erlang把&amp;ldquo;中国人&amp;rdquo;三字编译成不同的长度了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;4&amp;gt; test:run().&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;{match,[{0,12},{8,4}]}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;6&amp;gt; test:run().&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;{match,[{0,16},{12,4}]}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  11:59:36&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;是的 是的&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;深圳-燕尘(6108770)  11:59:49&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;windows 下不怪异啊。 windows 下就是 ，cmd 是 latin1 字符集， werl 是 unicode 字符集&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;深圳-燕尘(6108770)  12:01:37&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;我装了一个 latin1 的 suse 和 unicode 的 arch ，虚拟机。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px; color: #0000ff;"&gt;北京-坚强2002  12:02:34&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;明白 我被表面忽悠了 对的&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;1&amp;gt; "中国人".&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;"中国人"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;2&amp;gt; hd(v(1)).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;214&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;3&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12px;"&gt;对的&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;附录&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;strong&gt;附录一&amp;nbsp;&lt;/strong&gt;正则表达式相关的测试代码&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;测试数据:&lt;br/&gt;&lt;br/&gt;    Rec &lt;/span&gt;= "^[\x{4e00}-\x{9fff}]+$",          %&lt;span style="color: #000000;"&gt; 中文正则1&lt;br/&gt;    Rec &lt;/span&gt;= "^([\x81-\xfe][\x40-\xfe])+$",      %&lt;span style="color: #000000;"&gt; 中文正则2&lt;br/&gt;&lt;br/&gt;re() &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;   re:run(&lt;/span&gt;"hello 中国 ren", "[\x{4e00}-\x{9fff}]+"&lt;span style="color: #000000;"&gt;, [unicode]).&lt;br/&gt;&lt;br/&gt;re1(C) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;   re:run(C,&lt;/span&gt;"[\x{4e00}-\x{9fff}]+"&lt;span style="color: #000000;"&gt;, [unicode]).&lt;br/&gt; &lt;br/&gt;re3()&lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;  re:run(&lt;/span&gt;"中国人", "([\x81-\xfe][\x40-\xfe])+"&lt;span style="color: #000000;"&gt;, [unicode]).&lt;br/&gt;&lt;br/&gt;re4(C)&lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;  re:run(C, &lt;/span&gt;"([\x81-\xfe][\x40-\xfe])+"&lt;span style="color: #000000;"&gt;, [unicode]).&lt;br/&gt;&lt;br/&gt;环境1:Centos {encoding,unicode}&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;Eshell V5.&lt;/span&gt;9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt;&lt;span style="color: #000000;"&gt; text:re3().&lt;br/&gt;{match,[{&lt;/span&gt;0,16},{12,4&lt;span style="color: #000000;"&gt;}]}&lt;br/&gt;&lt;/span&gt;2&amp;gt; L="中国人"&lt;span style="color: #000000;"&gt;.&lt;br/&gt;[&lt;/span&gt;20013,22269,20154&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;3&amp;gt;&lt;span style="color: #000000;"&gt; text:re4(L).&lt;br/&gt;nomatch&lt;br/&gt;&lt;/span&gt;4&amp;gt;&lt;span style="color: #000000;"&gt; io:getopts().&lt;br/&gt;[{expand_fun,#Fun&lt;/span&gt;&amp;lt;group.0.33302583&amp;gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{echo,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{binary,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{encoding,unicode}]&lt;br/&gt;&lt;/span&gt;5&amp;gt; &lt;br/&gt;5&amp;gt;&lt;span style="color: #000000;"&gt; text:re1(L). &lt;br/&gt;{match,[{&lt;/span&gt;0,9&lt;span style="color: #000000;"&gt;}]}&lt;br/&gt;&lt;/span&gt;6&amp;gt; &lt;br/&gt;7&amp;gt;&lt;span style="color: #000000;"&gt; text:re(). &lt;br/&gt;nomatch&lt;br/&gt;&lt;/span&gt;8&amp;gt;&lt;span style="color: #000000;"&gt; &lt;br/&gt; &lt;br/&gt;环境2 :Centos {encoding,unicode}&lt;br/&gt;启动命令: LC_CTYPE&lt;/span&gt;=en_US.ISO-8859-1&lt;span style="color: #000000;"&gt; erl&lt;br/&gt;Eshell V5.&lt;/span&gt;9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; &lt;br/&gt;1&amp;gt;  L="中3".  &lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;L的内容是"中国人" 显示问题&lt;/span&gt;&lt;br/&gt;[228,184,173,229,155,189,228,186,186&lt;span style="color: #000000;"&gt;]&lt;br/&gt;&lt;/span&gt;2&amp;gt;&lt;span style="color: #000000;"&gt;  text:re3().&lt;br/&gt;{match,[{&lt;/span&gt;0,16},{12,4&lt;span style="color: #000000;"&gt;}]}&lt;br/&gt;&lt;/span&gt;3&amp;gt;&lt;span style="color: #000000;"&gt;  text:re4(L).&lt;br/&gt;{match,[{&lt;/span&gt;0,4},{0,4&lt;span style="color: #000000;"&gt;}]}&lt;br/&gt;&lt;/span&gt;4&amp;gt;&lt;span style="color: #000000;"&gt; io:getopts().&lt;br/&gt;[{expand_fun,#Fun&lt;/span&gt;&amp;lt;group.0.33302583&amp;gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{echo,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{binary,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;},&lt;br/&gt;{encoding,latin1}]&lt;br/&gt;&lt;/span&gt;5&amp;gt;&lt;span style="color: #000000;"&gt;  text:re1(L).&lt;br/&gt;nomatch&lt;br/&gt;&lt;/span&gt;6&amp;gt;&lt;span style="color: #000000;"&gt;  text:re(). &lt;br/&gt;nomatch&lt;br/&gt;&lt;/span&gt;7&amp;gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;附录二&lt;/strong&gt;&amp;nbsp;数据类型内存分配对照表&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012060112155378.png" alt="" /&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;img id="ViewPicture1_GalleryImage" src="http://images.cnblogs.com/cnblogs_com/me-sa/99450/r_Toolkit.png" alt="Toolkit" /&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;参考资料&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[1] Erlang binary strings by default&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/9984428/erlang-binary-strings-by-default"&gt;http://stackoverflow.com/questions/9984428/erlang-binary-strings-by-default&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[2] Erlang and binary with cyrillic &amp;nbsp;&lt;a href="http://stackoverflow.com/questions/10596193/erlang-and-binary-with-cyrillic"&gt;http://stackoverflow.com/questions/10596193/erlang-and-binary-with-cyrillic&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[3] yaws unicode symbols in {html, &amp;hellip;}&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/9513623/yaws-unicode-symbols-in-html"&gt;http://stackoverflow.com/questions/9513623/yaws-unicode-symbols-in-html&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[4] Erlang, io_lib and unicode&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/8622694/erlang-io-lib-and-unicode"&gt;http://stackoverflow.com/questions/8622694/erlang-io-lib-and-unicode&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[5] erlang对中文支持的问题 &amp;nbsp;&lt;a href="http://erlangqa.com/385/erlang%E5%AF%B9%E4%B8%AD%E6%96%87%E6%94%AF%E6%8C%81%E7%9A%84%E9%97%AE%E9%A2%98"&gt;地址&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[6]&amp;nbsp;Erlang的Unicode支持 &amp;nbsp;&lt;a href="http://erlangdisplay.iteye.com/blog/364389"&gt;http://erlangdisplay.iteye.com/blog/364389&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[7]&amp;nbsp;EEP10&amp;nbsp;&lt;a href="http://www.erlang.org/eeps/eep-0010.html"&gt;http://www.erlang.org/eeps/eep-0010.html&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[8] GB2312&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/GB2312"&gt;http://zh.wikipedia.org/wiki/GB2312&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[9]&amp;nbsp;如何从一个字符串中匹配出里面的中文&amp;nbsp;&lt;a href="http://erlangqa.com/382/%E5%A6%82%E4%BD%95%E4%BB%8E%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E5%8C%B9%E9%85%8D%E5%87%BA%E9%87%8C%E9%9D%A2%E7%9A%84%E4%B8%AD%E6%96%87"&gt;地址&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;晚安!&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2529214.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/31/erlang-unicode.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/24/2517306.html</id><title type="text">The Matrix Revolutions</title><summary type="text"> 一个负责运行虚拟现实（VR）系统的主机（Main Frame），长期运行，抛出了6次异常，前5次异常触发自动更新程序AutoUpdater完成自身软件升级，触发需要使用密钥（Key Maker）通过验证。第六次异常处理执行没有按照之前的异常处理方式，一个影响就是VR中的垃圾清理程序不断的使用VR数据进行深拷贝（Deep Copy），结果VR中的天气虚拟系统、动力系统甚至包括自动更新程序的守护进程全部被结束掉了。主机通过所构建的另外一个虚拟现实系统再次抛出该异常（rethrow）,这一次导致整个运行时重构升级，完成了第六次升级。这不是系统升级报告,这是当年我看"黑客帝国"三部曲之后的笔记; 最近在读KK的"科技要什么",经常会想到这部很久以前的电影,翻出来以前的笔记看一下;之前看KK的"失控",感觉第一章就是黑客帝国开场的情景,一起重温一下吧:" 我被关闭在密不透气的玻璃小屋里......</summary><published>2012-05-24T15:36:00Z</published><updated>2012-05-24T15:36:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/24/2517306.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/24/2517306.html"/><content type="html">&lt;p&gt;&amp;nbsp; &amp;nbsp; &lt;span style="font-size: 18pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 宋体;"&gt;&lt;span style="font-size: 18pt;"&gt;一个&lt;/span&gt;负责运行虚拟现实（VR）系统的主机（Main Frame），长期运行，抛出了6次异常，前5次异常触发自动更新程序AutoUpdater完成自身软件升级，触发需要使用密钥（Key Maker）通过验证。第六次异常处理执行没有按照之前的异常处理方式，一个影响就是VR中的垃圾清理程序不断的使用VR数据进行深拷贝（Deep Copy），结果VR中的天气虚拟系统、动力系统甚至包括自动更新程序的守护进程全部被结束掉了。主机通过所构建的另外一个虚拟现实系统再次抛出该异常（rethrow）,这一次导致整个运行时重构升级，完成了第六次升级。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;这不是系统升级报告,这是当年我看"黑客帝国"三部曲之后的笔记;&amp;nbsp;最近在读KK的"科技要什么",经常会想到这部很久以前的电影,翻出来以前的笔记看一下;之前看KK的"失控",感觉第一章就是黑客帝国开场的情景,一起重温一下吧:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;div&gt;&lt;img style="float: left; margin-left: 12px; margin-right: 12px;" src="http://pic002.cnblogs.com/images/2012/17329/2012052423161725.png" alt="" /&gt;&lt;span&gt;&amp;nbsp;&lt;span style="font-family: 楷体; color: #000000;"&gt; &amp;nbsp;&lt;span style="font-family: 宋体; font-size: 13px;"&gt; 我被关闭在密不透气的玻璃小屋里。在这里，我吸入的是自己呼出的气体，不过，在风扇的吹动下，空气依然清新。由众多的导管、线缆、植物和沼泽微生物构成的系统回收了我的尿液和粪便，并将其还原成水和食物供我食用。说真的，食物的味道不错，水也很好喝。&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #000000; font-size: 13px;"&gt;&lt;br /&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 昨夜，外面下了雪。玻璃小屋里却依然温暖、湿润而舒适。今天早上，厚厚的内窗上挂满了凝结的水珠。小屋里到处都是植物。大片大片的香蕉叶环绕在我的四周，那鲜亮的黄绿色暖人心房。纤细的青豆藤缠绕着，爬满了所有的墙面。屋内大约一半的植物都可食用，而我的每一顿大餐都来源于它们。&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #000000; font-size: 13px;"&gt;&lt;br /&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个小屋实际上是一个太空生活试验舱。我周边大气的循环再利用完全依赖于植物及其扎根的土壤，以及那些在树叶间穿来穿去的、嗡嗡作响的管道系统。不管是这些绿色植物，还是那些笨重的机器，单靠它们自己，都不足以保证我在这个空间的生存。确切地说，是阳光供养的生物和机油驱动的机械共同确保了我的生存。在这个小屋内，生物和人造物已经融合成为一个稳定的系统，其目的就是养育更高级的复杂物&amp;mdash;&amp;mdash;当下而言，就是我。&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #000000; font-size: 13px;"&gt;&lt;br /&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在这个千年临近结束的时候，发生在这个玻璃小屋里的事情，也正在地球上大规模地上演着&amp;mdash;&amp;mdash;只不过不那么明晰。造化所生的自然王国和人类建造的人造国度正在融为一体。机器，正在生物化；而生物，正在工程化。&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="color: #000000; font-size: 13px;"&gt;&lt;br /&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这种趋势正验证着某些古老的隐喻&amp;mdash;&amp;mdash;将机器比喻为生物，将生物比喻为机器。那些比喻由来已久，古老到第一台机器诞生之时。如今，那些久远的隐喻不再只是诗意的遐想，它们正在变为现实&amp;mdash;&amp;mdash;一种积极有益的现实。&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 黑体;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 人造与天生的联姻正是本书的主题。技术人员归纳总结了生命体和机器之间的逻辑规律，并一一应用于建造极度复杂的系统；他们正在如魔法师一般召唤出制造物和生命体并存的新奇装置。从某种程度上来说，是现有技术的局限性迫使生命与机械联姻，为我们提供有益的帮助。由于我们自己创造的这个世界变得过于复杂，我们不得不求助于自然世界以了解管理它的方法。这也就意味着，要想保证一切正常运转，我们最终制造出来的环境越机械化，可能越需要生物化。我们的未来是技术性的，但这并不意味着未来的世界一定会是灰色冰冷的钢铁世界。相反，我们的技术所引导的未来，朝向的正是一种新生物文明。&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp; &lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; 人类在创造复杂机械的进程中，一次又一次地回归自然去寻求指引。因此自然绝不仅仅是一个储量丰富的生物基因库，为我们保存一些尚未面世的救治未来疾患的药物。自然还是一个&amp;ldquo;文化基因库&amp;rdquo;，是一个创意工厂。在丛林中的每一个蚁丘中都隐藏着鲜活的、后工业时代的壮丽蓝图。那些飞鸟鸣虫，那些奇花异草，还有那些从这些生命中汲取了能量的原生态的人类文化，都值得我们去呵护&amp;mdash;&amp;mdash;不为别的，就为那些它们所蕴含着的后现代隐喻。对新生物文明来说，摧毁一片草原，毁掉的不仅仅是一个生物基因库，还毁掉了一座蕴藏着各种启示、洞见和新生物文明模型的宝藏。 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; &amp;nbsp; 向机器中大规模地植入生物逻辑有可能使我们满怀敬畏。当人造与天生最终完全统一的时候，那些由我们制造出来的东西将会具备学习、适应、自我治愈，甚至是进化的能力。这是一种我们还很难想象的力量。数以百万计的生物机器汇聚在一起的智能，也许某天可以与人类自己的创新能力相匹敌。人类的创造力，也许总是属于那种华丽绚烂的类型，但还有另外一种类型的创造力值得一提&amp;mdash;&amp;mdash;一种由无数默默无闻的&amp;ldquo;零件&amp;rdquo;通过永不停歇的工作而形成的缓慢而宽广的创造力。 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; &amp;nbsp; 在将生命的力量释放到我们所创造的机器中的同时，我们就丧失了对他们的控制。他们获得了野性，并因野性而获得一些意外和惊喜。之后，就是所有造物主都必须面对的两难窘境：他们将不再完全拥有自己最得意的创造物。 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 13px;"&gt;    人造世界就像天然世界一样，很快就会具有自治力、适应力以及创造力，也随之失去我们的控制。但在我看来，这却是个最美妙的结局。 &lt;/span&gt;&lt;/p&gt;&lt;span style="color: #000000; font-size: 13px;"&gt;&lt;span style="font-family: 黑体;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 14px;"&gt;&lt;span style="font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012052501001462.jpg" alt="" /&gt;&lt;/p&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;span&gt;&lt;span style="font-family: 楷体;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2517306.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/24/2517306.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/22/erlang-code-snippet-2.html</id><title type="text">[Erlang 0061] Erlang Code Snippet  Ⅱ</title><summary type="text">整理了最近一段时间记录的Erlang代码片段,还有大量简短的代码都已经整理在官方文档的PDF中.从开始学习Erlang,写的测试代码都会整理到PDF中,从这个习惯中得益匪浅.</summary><published>2012-05-22T14:05:00Z</published><updated>2012-05-22T14:05:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/22/erlang-code-snippet-2.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/22/erlang-code-snippet-2.html"/><content type="html">&lt;div&gt;&lt;span style="font-size: 12px;"&gt;&amp;nbsp; 整理了最近一段时间记录的Erlang代码片段,还有大量简短的代码都已经整理在官方文档的PDF中.从开始学习Erlang,写的测试代码都会整理到PDF中,从这个习惯中得益匪浅.可以在PDF上做批注,图形的工具我用的是:&lt;a href="http://www.tracker-software.com/product/pdf-xchange-viewer" target="_blank"&gt;PDF-XChange Viewer&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;上一次代码片段整理:&lt;a class="titlelink" href="http://www.cnblogs.com/me-sa/archive/2012/03/04/erlang0043.html"&gt;[Erlang 0043] Erlang Code Snippet&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;record 转 proplist&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @spec record_to_proplist(Record, Fields) -&amp;gt; proplist()&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @doc calls record_to_proplist/3 with a default TypeKey of '__record'&lt;/span&gt;&lt;br/&gt;record_to_proplist(Record, Fields) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    record_to_proplist(Record, Fields, &lt;/span&gt;'__record'&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @spec record_to_proplist(Record, Fields, TypeKey) -&amp;gt; proplist()&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @doc Return a proplist of the given Record with each field in the&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;      Fields list set as a key with the corresponding value in the Record.&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;      TypeKey is the key that is used to store the record type&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;      Fields should be obtained by calling record_info(fields, record_type)&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;      where record_type is the record type of Record&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;record_to_proplist(Record, Fields, TypeKey)&lt;br/&gt;  &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;when&lt;/span&gt; tuple_size(Record) - 1 =:= length(Fields) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    lists:zip([TypeKey &lt;/span&gt;| Fields], tuple_to_list(Record)).&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #464646;"&gt;测试代码:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Eshell V5.9&amp;nbsp; (abort with ^G)&lt;br /&gt;1&amp;gt;&amp;nbsp; rd(person,{name,id,age}).&lt;br /&gt;person&lt;br /&gt;2&amp;gt; mochiweb_util:record_to_proplist(#person{}, record_info(fields, person)).&lt;br /&gt;[{'__record',person},&lt;br /&gt;{name,undefined},&lt;br /&gt;{id,undefined},&lt;br /&gt;{age,undefined}]&lt;br /&gt;3&amp;gt; mochiweb_util:record_to_proplist(#person{age=12,name=zen,id=2396}, record_info(fields, person)).&lt;br /&gt;[{'__record',person},{name,zen},{id,2396},{age,12}]&lt;br /&gt;4&amp;gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;保证应用程序已经启动&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @spec ensure_started(App::atom()) -&amp;gt; ok&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @doc Start the given App if it has not been started already.&lt;/span&gt;&lt;br/&gt;ensure_started(App) -&amp;gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; application:start(App) &lt;span style="color: #0000ff;"&gt;of&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;        ok &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;            ok;&lt;br/&gt;        {error, {already_started, App}} &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;            ok&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;.&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;解析IP地址 是否支持IP V6&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;判断是否支持IPV6&lt;/span&gt;&lt;br/&gt;ipv6_supported() -&amp;gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;catch&lt;/span&gt; inet:getaddr("localhost", inet6)) &lt;span style="color: #0000ff;"&gt;of&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;        {ok, _Addr} &lt;/span&gt;-&amp;gt;&lt;br/&gt;            &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        {error, _} &lt;/span&gt;-&amp;gt;&lt;br/&gt;            &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt; &lt;br/&gt;&lt;/span&gt;6&amp;gt; inet_parse:address("192.168.0.1"&lt;span style="color: #000000;"&gt;).&lt;br/&gt;{ok,{&lt;/span&gt;192,168,0,1}}&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;整形幂运算&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @spec int_pow(X::integer(), N::integer()) -&amp;gt; Y::integer()&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @doc  Moderately efficient way to exponentiate integers.&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;       int_pow(10, 2) = 100.&lt;/span&gt;&lt;br/&gt;int_pow(_X, 0) -&amp;gt;&lt;br/&gt;    1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;int_pow(X, N) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;when&lt;/span&gt; N &amp;gt; 0 -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    int_pow(X, N, &lt;/span&gt;1&lt;span style="color: #000000;"&gt;).&lt;br/&gt; &lt;br/&gt;int_pow(X, N, R) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;when&lt;/span&gt; N &amp;lt; 2 -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    R &lt;/span&gt;*&lt;span style="color: #000000;"&gt; X;&lt;br/&gt;int_pow(X, N, R) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    int_pow(X &lt;/span&gt;* X, N &lt;span style="color: #0000ff;"&gt;bsr&lt;/span&gt; 1, &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; N &lt;span style="color: #0000ff;"&gt;band&lt;/span&gt; 1 &lt;span style="color: #0000ff;"&gt;of&lt;/span&gt; 1 -&amp;gt; R * X; 0 -&amp;gt; R &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;).&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&lt;span style="color: #464646;"&gt;测试代码:&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;2&amp;gt; math:pow(2,3).&lt;br /&gt;8.0&lt;br /&gt;3&amp;gt; test:int_pow(2,3).&lt;br /&gt;8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;向上取整&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @spec int_ceil(F::float()) -&amp;gt; integer()&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt; @doc  Return the ceiling of F as an integer. The ceiling is defined as&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;       F when F == trunc(F);&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;       trunc(F) when F &amp;amp;lt; 0;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br/&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;       trunc(F) + 1 when F &amp;amp;gt; 0.&lt;/span&gt;&lt;br/&gt;int_ceil(X) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    T &lt;/span&gt;=&lt;span style="color: #000000;"&gt; trunc(X),&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; (X - T) &lt;span style="color: #0000ff;"&gt;of&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;        Pos &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;when&lt;/span&gt; Pos &amp;gt; 0 -&amp;gt; T + 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;        _ &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt; T&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;.&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;在Erlang Shell中生成随机字符串&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;2&amp;gt; F=&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(Len, AllowedChars) -&amp;gt;    lists:foldl(&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(_, Acc) -&amp;gt; [lists:nth(random:uniform(length(AllowedChars)),  AllowedChars)]  ++ Acc  &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;, [], lists:seq(1, Len)) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.12.111823515&amp;gt;&lt;br/&gt;3&amp;gt; F(4,"0123456789abcdefghijklmnopqrstuvwxyz"&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;"iyqf"&lt;br/&gt;4&amp;gt; F(4,"0123456789abcdefghijklmnopqrstuvwxyz"&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;"owlb"&lt;br/&gt;5&amp;gt; F(4,"0123456789abcdefghijklmnopqrstuvwxyz"&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;"75lh"&lt;br/&gt;6&amp;gt; F(4,"0123456789abcdefghijklmnopqrstuvwxyz"&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;"7k5p"&lt;br/&gt;7&amp;gt; F(4,"0123456789abcdefghijklmnopqrstuvwxyz"&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;"k0fg"&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;产生GUID&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;random_token() -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    Term &lt;/span&gt;=&lt;span style="color: #000000;"&gt; term_to_binary({node(), make_ref()}),&lt;br/&gt;    Digest &lt;/span&gt;=&lt;span style="color: #000000;"&gt; erlang:md5(Term),&lt;br/&gt;    binary_to_hex(Digest).&lt;br/&gt;&lt;br/&gt;binary_to_hex(Bin) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;when&lt;/span&gt; is_binary(Bin) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    [oct_to_hex(N) &lt;/span&gt;|| &amp;lt;&amp;lt;N:4&amp;gt;&amp;gt; &amp;lt;=&lt;span style="color: #000000;"&gt; Bin].&lt;br/&gt;&lt;br/&gt;oct_to_hex(&lt;/span&gt;0) -&amp;gt; $0&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;1) -&amp;gt; $1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;2) -&amp;gt; $2&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;3) -&amp;gt; $3&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;4) -&amp;gt; $4&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;5) -&amp;gt; $5&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;6) -&amp;gt; $6&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;7) -&amp;gt; $7&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;8) -&amp;gt; $8&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;9) -&amp;gt; $9&lt;span style="color: #000000;"&gt;;&lt;br/&gt;oct_to_hex(&lt;/span&gt;10) -&amp;gt;&lt;span style="color: #000000;"&gt; $a;&lt;br/&gt;oct_to_hex(&lt;/span&gt;11) -&amp;gt;&lt;span style="color: #000000;"&gt; $b;&lt;br/&gt;oct_to_hex(&lt;/span&gt;12) -&amp;gt;&lt;span style="color: #000000;"&gt; $c;&lt;br/&gt;oct_to_hex(&lt;/span&gt;13) -&amp;gt;&lt;span style="color: #000000;"&gt; $d;&lt;br/&gt;oct_to_hex(&lt;/span&gt;14) -&amp;gt;&lt;span style="color: #000000;"&gt; $e;&lt;br/&gt;oct_to_hex(&lt;/span&gt;15) -&amp;gt;&lt;span style="color: #000000;"&gt; $f.&lt;br/&gt; &lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #464646;"&gt;测试代码:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&lt;span style="color: #464646;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;1&amp;gt; test:random_token().&lt;br /&gt;"db6f50cc40d54e338b0362c05d1b0295"&lt;br /&gt;2&amp;gt; test:random_token().&lt;br /&gt;"98b784e379dee8fa68ff863ba6c02cff"&lt;br /&gt;3&amp;gt; test:random_token().&lt;br /&gt;"7bc7db7cbab45025adaa02e28cc3972d"&lt;br /&gt;4&amp;gt; test:random_token().&lt;br /&gt;"0f794a8aed063184393bc5bb883f53bf"&lt;br /&gt;5&amp;gt; test:random_token().&lt;br /&gt;"4e18f2879d8d05e86445082bf4a46f19"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;YA生成随机字符串&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;-&lt;span style="color: #000000;"&gt;define(SAFE_CHARS, {$a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m,&lt;br/&gt;                     $n, $o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z,&lt;br/&gt;                     $A, $B, $C, $D, $E, $F, $G, $H, $I, $J, $K, $L, $M,&lt;br/&gt;                     $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z,&lt;br/&gt;                     $&lt;/span&gt;0, $1, $2, $3, $4, $5, $6, $7, $8, $9&lt;span style="color: #000000;"&gt;, $_}).&lt;br/&gt;&lt;br/&gt;rngchars(&lt;/span&gt;0) -&amp;gt;&lt;br/&gt;    ""&lt;span style="color: #000000;"&gt;;&lt;br/&gt;rngchars(N) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    [rngchar() &lt;/span&gt;| rngchars(N - 1&lt;span style="color: #000000;"&gt;)].&lt;br/&gt;&lt;br/&gt;rngchar() &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    rngchar(crypto:rand_uniform(&lt;/span&gt;0, tuple_size(?&lt;span style="color: #000000;"&gt;SAFE_CHARS))).&lt;br/&gt;&lt;br/&gt;rngchar(C) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;    element(&lt;/span&gt;1 + C, ?SAFE_CHARS).&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;&lt;span style="color: #464646;"&gt;测试代码:&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;strong&gt;&lt;span style="color: #464646;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;10&amp;gt; test:rngchars(6).&lt;br /&gt;"vlrLnt"&lt;br /&gt;11&amp;gt; test:rngchars(6).&lt;br /&gt;"y_fvQ_"&lt;br /&gt;12&amp;gt; test:rngchars(6).&lt;br /&gt;"VpOg8w"&lt;br /&gt;13&amp;gt; test:rngchars(6).&lt;br /&gt;"YzTnps"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;好代码,一次擦肩而过可能就再也见不到了哦&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012052222042445.jpg" alt="" /&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2513934.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/22/erlang-code-snippet-2.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/20/2510564.html</id><title type="text">[Erlang 0060] Joe Armstrong 论文《面向软件错误构建可靠的分布式系统》笔记</title><summary type="text">周末读了两篇论文"On Designing and Deploying Internet-Scale Services"和Joe Armstrong的论文"面对软件错误构建可靠的分布式系统",这两篇论文实战内容相当多,整理笔记于此,备忘.</summary><published>2012-05-20T07:14:00Z</published><updated>2012-05-20T07:14:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/20/2510564.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/20/2510564.html"/><content type="html">&lt;div&gt;&lt;span&gt;&amp;nbsp; 周末读了两篇论文"On Designing and Deploying Internet-Scale Services"和Joe Armstrong的论文"面对软件错误构建可靠的分布式系统",这两篇论文实战内容相当多,整理笔记于此,备忘.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;On Designing and Deploying Internet-Scale Services [&lt;a href="http://static.usenix.org/event/lisa07/tech/full_papers/hamilton/hamilton_html/" target="_blank"&gt;HTML&lt;/a&gt;]&lt;/div&gt;&lt;div&gt;&lt;span&gt;英文版"Making reliable distributed systems in the presence of sodware errors" &amp;nbsp;[&lt;a href="http://pubftp0.availo.se/pub/FreeBSD/distfiles/erlang-doc/r13b01/armstrong_thesis_2003.pdf"&gt;PDF&lt;/a&gt;]&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;中文版 《面向软件错误构建可靠的分布式系统》 [&lt;a href="http://man.lupaworld.com/content/other/erlang.pdf"&gt;PDF&lt;/a&gt;]&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;架构的定义&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; An architecture is the set of signiﬁcant decisions about the organization of a sodware system, the selection of the structural elements&amp;nbsp;and their interfaces by which the system is composed, together with&amp;nbsp;their behaviour as speciﬁed in the collaborations among those elements, the composition of these structural and behavioural elements&amp;nbsp;into progressively larger subsystems, and the architectural style that&amp;nbsp;guides this organization&amp;mdash;these elements and their interfaces, their&amp;nbsp;collaborations, and their composition.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Booch, Rumbaugh, and Jacobson [19]&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; 在我接触到的架构定义中,Joe Armstrong论文中提到的定义相当务实,相当具有实践指导价值;首先和Martin Fowler等人对架构的共识是架构是一组系统组织方式的重要决策;决策包含系统有哪些构成元素,元素之间的接口,元素之间的协作方式;是一种把这些结构和行为元素构建为更大子系统的的合成方式;也是一种构建风格,在其指导下把元素,元素接口,元素协作和合成方式组织起来.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012052015122249.png" alt="" /&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; 把架构的抽象概念映射到具体实践过程,可以从六个具体方面去考量,这时候我们已经从万里高空下降到陆地上了.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;1．问题领域&amp;mdash;&amp;mdash;我们的架构是为解决什么类型的问题而设计的?软件架构一定不是通用的,而是为解决某一类特定问题而设计的.缺少了关于用来解决哪类问题的描述的架构是不完整的.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;笔记&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;:同样的,缺少上下文描述的编程语言比较也只是一场关公战秦琼的乱斗而已;遇到过一些"技术牛人"身居要位,硬是把之前项目的设计方案强制应用在当前的项目上,这都不是偷懒那样简单,而是缺少对项目负责的专业态度.而更为糟糕的是一旦项目做失败了,就甩手走人,留下一个烂尾的工程留给团队;对团队的伤害,需要更长时间进行修复.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span&gt;2．哲学&amp;mdash;&amp;mdash;&amp;nbsp; 软件构造方法背后的原理是什么?架构的核心思想是什么?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;笔记&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;:在解决了问题或者完成了一个设计之后,我们一定要回顾一下解决问题的思路和设计的原理;具体的技术细节可能无法服用,但是思维方式和设计方法都是可以复用的.在阅读开源项目时,学习语言技巧是一方面,更为重要的是看这个项目是解决了什么问题,如何解决的,整体思路是怎样的.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;span&gt;3．软件构造指南&amp;mdash;&amp;mdash;我们如何来规划一个系统?我们需要一个明确的软件构造指南集.我们的系统将由一个程序员团队来编写和维护&amp;mdash;&amp;mdash;所以对所有的程序员和系统设计者来说,理解系统的架构和它的潜在哲学是很重要的.从实用性的角度来讲,这些知识以软件构造指南的方式表现出来更便于维持.一个完整的软件构造指南集包括编程规则集,例子程序和培训资料等等.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;笔记&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;:这个还是深有感触的,现在有一些项目比如PlayStation&amp;reg;Suite SDK把C#当作脚本使用,但是你会发现在这些项目里面虽然同是C#语言但无论是类库组织还是命名规范都是有自己的规则和风格的.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;4．预先定义好的部件&amp;mdash;&amp;mdash;以&amp;ldquo;从一组预先定义好的部件中选择&amp;rdquo;的方式进行设计远比&amp;ldquo;从头设计&amp;rdquo;的方式要来得容易.Erlang 的OTP库包含了一个完整的现成部件集(称之 behaviour 库),一些常用的系统都可以使用这些部件构建起来.例如 gen_server 这种 behaviour 就可以用来构建client-server 系统,gen_event 这种 behaviour 可以用来构建基于事件(event-based)的程序.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;笔记&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;:学习语言,其中一个重要的部分就是掌握这个语言所提供的类库;一方面是不重复造轮子,能够直接使用高质量类库;另一方面从类库中可以学习这种语言的编程风格.&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;5．描述方式&amp;mdash;&amp;mdash;我们如何描述某一部件的接口?我们如何描述系统中两个部件之间的通信协议?我们如何来描述系统中的静态和动态结构?为了回答这些问题,我们将介绍一些专门的符号.其中一些用来描述程序的API,而其他的则用来描述协议和系统结构。&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;笔记&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;:学习一种新知识,其中的门槛一方面是来自于概念,另一方面就是来自于符号系统;这两种都是对信息进行了简化,背后包含了较大的信息量,没有额外的信息支持难以理解.在最初接触一种新知识的时候,由于不了解这个领域的术语和概念,我们甚至都不能正确的描述遇到的问题.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;6．配置方式&amp;mdash;&amp;mdash;我们如何来启动,停止和配置我们的系统?我们可以在系统工作过程中进行重配置吗?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;笔记&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;:编程完成业务功能并没有万事大吉,还要考虑到配置,部署,这些问题的考虑时机甚至在设计之初就要考虑;针对不同的硬件设备,配置也有所不同;考虑到日常维护,还要准备一些给运维使用的脚本.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;Erlang 故障隔离&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;为了构建出在软件存在错误的时候仍具有合理行为的可容错软件系统,Erlang的解决问题的思路是:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;1.任务层次化,尽力完成顶层任务&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;2.如果完成任务过程中出现错误,如果无法纠正错误,就立即取消重新启动新的任务&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;这其中最本质的问题就是故障隔离,操作系统通过进程的概念实现了故障隔离,&lt;span&gt;进程提供了保护区域,一个进程出错,不会影响到其他进程的运行.不同程序员编写的不同应用程序分别跑在不同的进程中; 一个应用程序的错误不会对系统中运行&lt;/span&gt;的其他应用程序产生副作用.这种选择当然满足了初步的要求.然而因为所有进程使用同一片 CPU,同一块物理内存,所以当不同进程争抢 CPU 资源或者使用大量内存的时候,还是可能对系统中的其他进程产生负面影响. 进程间的相互冲突程度取决于操作系统的设计特性.&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Erlang进程和并发编程是语言的一部分,而不是由宿主操作系统提供的,Erlang应用程序是通过大量互相通信的并行进程构建起来的,这样做的原因是:&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;架构基础设施&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;&amp;mdash;&amp;mdash;我们可以用一组相互通信的进程组织起我们的系统,并定义出进程间消息传递的通道,我们就可以很方便地把系统划分成定义良好的子部件,并可以对这些子部件进行单独实现和测试.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;巨大的潜在效率&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;&amp;mdash;&amp;mdash;设计成以许多独立的并行进程来实现的系统,可以&lt;/span&gt;很方便地实现在多处理器上,或者运行在分布式的处理器网络上. 注意这种效率的提升只是潜在的,只有当应用程序可以被分解成许多真正独立的任务时,才能产生实效.如果任务之间有很强的数据依赖,这种提升往往是不可能的.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;strong&gt;故障隔离&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;&amp;mdash;&amp;mdash;没有共享数据的并发进程提供了一种强大的故障隔离方法.一个并发进程的软件错误不会影响到系统中其他进程的运行.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;在并发的这三种用法中,前两条并不是其本质特性,可以由某种内置的调度程序通过在进程间提供不同的伪并行(pseudo-parallel)时分方式来获得.第三个特性对于编写可容错系统的软件来说,则是&lt;/span&gt;&lt;span&gt;&lt;strong&gt;本质&lt;/strong&gt;&lt;/span&gt;&lt;span&gt;性的.每一项独立的活动都在一个完全独立的进程中来执行.这些进程没有共享数据,进程之间只通&lt;/span&gt;过消息传递的方式进行通信,这就限制了软件错误造成的影响.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 一旦进程之间共享有任何公共资源,譬如内存,或指向内存的指针,或互斥体等等,一个进程中的一个软件错误破坏共享资源的可能性就存在.因为消除大型软件系统中的这类软件错误仍然是一个未解的难题,所以我认为构建大型的可靠系统的唯一现实的方法就是把系统分解成许多独立的并行进程, 并为监控和重启这些进程提供一些机制,&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;从某种意义上讲，操作系统提供了&amp;ldquo;被编程语言设计者遗忘了的东西&amp;rdquo;.但是在 Erlang 这样的编程语言中, 操作系统是几乎不需要的.OS真正提供给 Erlang的只是一些设备驱动程序,而 OS提供的诸如进程,消息传递,调度,内存管理等等机制都不需要.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;面向并发编程语言COPL&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; COPL编写这样的并发程序相当容易,它有三个步骤:&lt;br /&gt;1．从真实世界中的活动中识别出真正的并发活动&amp;nbsp;&lt;br /&gt;2．识别出并发活动之间的所有消息通道&lt;br /&gt;3．写下能够在不同的消息通道中流通的所有消息&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;值得注意的是,COPL 提供的并发性一定是真正的并发性，因此以进程的形式存在的对象都是真正并发的,进程间的消息传递也是真正的异步消息,而不像许多面向对象语言中一样是通过远程过程调用(remote procedure call)来冒充.&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;Erlang世界观概览&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;span&gt;&amp;bull; Everything is a process.&lt;br /&gt;&amp;bull; Processes are strongly isolated.&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span&gt;&amp;bull; Process creation and destruction is a lightweight operation.&lt;/span&gt;&lt;/div&gt;&lt;span&gt;&amp;bull; Message passing is the only way for processes to interact.&lt;br /&gt;&amp;bull; Processes have unique names.&lt;br /&gt;&amp;bull; If you know the name of a process you can send it a message.&lt;br /&gt;&amp;bull; Processes share no resources.&lt;br /&gt;&amp;bull; Error handling is non-local.&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span&gt;&amp;bull; Processes do what they are supposed to do or fail.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;思维导图&lt;/strong&gt;&lt;/p&gt;&lt;div id="__ss_12993720" style="width: 477px;"&gt; &lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a title="Erlang" href="http://www.slideshare.net/ligaoren/erlang-12993720" target="_blank"&gt;Erlang&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/12993720" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="1024" height="1024"&gt;&lt;/iframe&gt;&lt;div style="padding: 5px 0 12px;"&gt; View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;documents&lt;/a&gt; from &lt;a href="http://www.slideshare.net/ligaoren" target="_blank"&gt;ligaoren&lt;/a&gt; &lt;/div&gt; &lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2510564.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/20/2510564.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/17/erlang-calendar-date-time.html</id><title type="text">[Erlang 0059] Erlang日期与时间处理</title><summary type="text">软件开发有两个概念是和地区区域相关的:字符编码和时间;编码和时间的规范演变过程中有文化的冲突有历史的遗留,是软件开发中充满人文气息的一角;关于字符编码我之前整理过一篇文章,这部分知识很有意思,特别是格列佛游记所引出的大端小端概念,妙趣横生;平时笔记中也零零散散记录了一些和时间处理相关的内容,今天按图索骥把相关的资料整理汇集于此.</summary><published>2012-05-17T14:49:00Z</published><updated>2012-05-17T14:49:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/17/erlang-calendar-date-time.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/17/erlang-calendar-date-time.html"/><content type="html">&lt;p&gt;&amp;nbsp; 在开发过程中,有两个概念是和地区区域相关的:字符编码和时间;编码和时间的规范演变过程中有文化的冲突有历史的遗留,是软件开发中充满人文气息的一角;关于字符编码我之前整理过一篇文章,&lt;a href="http://www.cnblogs.com/me-sa/archive/2011/12/25/erlang0024.html" target="_blank"&gt; [Erlang 0024]Erlang二进制数据处理&lt;/a&gt;&amp;nbsp;这部分知识很有意思,特别是格列佛游记所引出的大端小端概念,妙趣横生;平时笔记中也零零散散记录了一些和时间处理相关的内容,今天按图索骥把相关的资料整理汇集于此.&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; 首先把时间相关的概念解释一下:&lt;/span&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;有关时间的概念&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;strong&gt;GMT时间&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; 格林尼治标准时间(Greenwich Mean Time ,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间，因为本初子午线被定义在通过那里的经线.自1924年2月5日开始，格林尼治天文台每隔一小时会向全世界发放调时信息.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 理论上来说，格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时的时间.由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能与实际的太阳时有误差,最大误差达16分钟.由于地球每天的自转是有些不规则的，而且正在缓慢减速,因此格林尼治时间已经不再被作为标准时间使用.现在的标准时间，是由原子钟报时的协调世界时(UTC).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;UTC时间&amp;nbsp;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; UTC时间是 Universal Time, Coordinated的缩写;中文名为协调世界时,又称世界标准时间或世界协调时间;这个略显怪异的名字来由是这样的:国际电信联盟希望协调世界时能够在所有语言有单一的缩写.英语和法语区的人同时希望各自的语言缩写,CUT和TUC,能够成为国际标准.结果最后妥协使用UTC.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;这套时间系统被应用于许多互联网和万维网的标准中,例如,网络时间协议就是协调世界时在互联网中使用的一种方式.在军事和航空中，协调世界时区会使用&amp;ldquo;Z&amp;rdquo;来表示.&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;在中国大陆,港澳台的本地时间比UTC快8小时，就会写作UTC+8，俗称&lt;strong&gt;东8区&lt;/strong&gt;。如果是在本地时间比UTC时间慢的地区，例如夏威夷的时间是比UTC时间慢10小时，就会写作UTC-10，并俗称西10区。&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012051722330434.png" alt="" width="500" height="269" /&gt;&lt;/p&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;时区&lt;/strong&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; 理论时区以被15整除的子午线为中心,向东西两侧延伸7.5度,即每15&amp;deg;划分一个时区,这是理论时区.理论时区的时间采用其中央经线(或标准经线)的地方时.所以每差一个时区,区时相差一个小时,相差多少个时区,就相差多少个小时.东边的时区比西边的时区时间来得早.为了避免日期的紊乱，提出国际日期变更线的概念。为了避开国界线，有的时区的形状并不规则，而且比较大的国家以国家内部行政分界线为时区界线，这是实际时区，即法定时区.&lt;/div&gt;&lt;div&gt;所有的时区都相对于UTC时设定.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;UNIX时间戳&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; UNIX时间或称POSIX时间是UNIX或类UNIX系统使用的时间表示方式:从UTC时1970年1月1日0时0分0秒起至现在的总秒数.&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;2038年问题:现时大部分使用UNIX的系统都是32位元的,即它们会以32位二进制数字表示时间.但是它们最多只能表示至协调世界时间2038年1月19日3时14分07秒(二进制：01111111 11111111 11111111 11111111),在下一秒二进制数字会是10000000 00000000 00000000 00000000，这是负数，因此各系统会把时间误解作1901年12月13日20时45分52秒（亦有说回归到1970年）。这时可能会令软件发生问题，导致系统瘫痪。&lt;/div&gt;目前解决方案是把系统由32位元转为64位元系统。在64位系统下，此时间最多可以表示到292,277,026,596年12月4日15时30分08秒。&lt;div&gt;&amp;nbsp; 是不是想到了很久以前的千年虫问题?&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;公历&amp;nbsp;Gregorian calendar&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 公历是现在国际通用的历法,又称格列历,通称阳历.&amp;ldquo;阳历&amp;rdquo;又名&amp;ldquo;太阳历&amp;rdquo;,系以地球绕行太阳一周为一年,为西方各国所通用,故又名&amp;ldquo;西历&amp;rdquo;.公历定义了月,闰月等计算方式;能够废掉帝号纪年法,是文化上的一大进步.除了帝号纪年我国还有干支纪年法,这个很有意思,即把十天干(甲,乙,丙,丁,戊,己,庚,辛,壬,癸)和十二地支(子,丑,寅,卯,辰,巳,午,未,申,酉,戌,亥)分别组合起来,共配成六十组,用来表示年月日的次序,周而复始,循环使用.&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 2012年是壬辰年,呵呵,明白为什么好多人选择在今年生孩子了吧?&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;夏令时 DST&lt;/strong&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;p&gt;&lt;img style="float: right; margin-left: 10px; margin-right: 10px; margin-top: 5px; margin-bottom: 5px;" src="http://pic002.cnblogs.com/images/2012/17329/2012051722361243.png" alt="" /&gt;&lt;/p&gt;&amp;nbsp; &amp;nbsp; 电影《国家宝藏》里面有一个情节就是三个人看到美元背后的4:10以为来不及了,但是意识到夏时令之后,发现还有一个小时的时间,一切还来得及;那么什么是夏令时呢?&lt;/div&gt;&lt;div style="text-align: left;"&gt;&amp;nbsp; &amp;nbsp; 夏时制(Daylight Saving Time:DST)又称&amp;ldquo;日光节约时制&amp;rdquo;和&amp;ldquo;夏令时间&amp;rdquo;,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为&amp;ldquo;夏令时间&amp;rdquo;.一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电.各个采纳夏时制的国家具体规定不同.目前全世界有近110个国家每年要实行夏令时. 自2011年3月27日开始俄罗斯永久使用夏令时,把时间拨快一小时,不再调回.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;据称最早有夏令时构思的是本杰明&amp;middot;富兰克林&amp;nbsp; 夏令时的提出者本杰明&amp;middot;富兰克林（被印在100美元钞票上的人物）,他在任美国驻法国大使期间,由于习惯于当时美国农村贵族的早睡早起生活,早上散步时看到法国人10点才起床,夜生活过到深夜.于是他在1784年给《巴黎杂志》的编辑写了一封信,信上说法国人的生活习惯浪费了大好的阳光,建议他们早睡早起,说每年可以节约6千4百万磅蜡烛.但他当时并没有建议实行夏令时,只是建议人们应该早睡早起.直到1907年,一位英国建筑师威廉&amp;middot;维莱特（William Willett）才正式向英国议会提出夏时制的构思,主要是为了节省能源和提供更多的时间用来训练士兵,但议会经过辩论没有采纳.由于名声不及本杰明&amp;middot;富兰克林,所以人们很多都将本杰明&amp;middot;富兰克林当为夏时制的发明者而忽略了威廉&amp;middot;维莱特.&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;中国曾在1986-1991年推行夏时制,后停止原因是:1.区域辽阔大部分地区都没有必要实行2.中国大多数的平民都已习惯北京时间,实行夏令时对于他们来说难以接受,认为多此一举.3.夏时制使铁路和航班需要每年修改时间表,造成麻烦和不便.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;公元纪元&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;"公历纪元"是国际通行的纪年体系.以传说中耶稣基督的生年为公历元年,产生于基督教盛行的六世纪,当时，为了扩大教会的统治势力,神父们把任何事情都附会在基督教上.&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;日期时间格式化表示&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 文化差异下日期的表示方式也各有不同,就英语而言英联邦国家和美国就在日期表示惯用法上有不同;要想流畅的沟通就要有日期时间的表示规范,ISO 8601对日期时间表示做了详细的描述,可以看一下维基百科的简介.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Erlang Calendar&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;了解了这些之后,我们回归到技术之上,看一下Erlang中有关时间的计算,这基本上集中在&lt;a href="http://www.erlang.org/doc/man/calendar.html" target="_blank"&gt;calendar&lt;/a&gt;模块.&amp;nbsp;平时我们调用的erlang:now()得到的是从 00:00 GMT, January 1, 1970起经过的时间,结果构成为:{MegaSecs, Secs, MicroSecs},对于公历计时的起点Erlang回溯到0年.若计算时间差,需转成世界时间之后再进行计算;时间运算基于下面的规则:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;strong&gt;erlang:now()&lt;/strong&gt; Returns the tuple {MegaSecs, Secs, MicroSecs} which is the elapsed time since 00:00 GMT, January 1, 1970 (zero hour) on the assumption that the underlying OS supports this. Otherwise, some other point in time is chosen. It is also guaranteed that subsequent calls to this BIF returns continuously increasing values. Hence, the return value from now() can be used to generate unique time-stamps, and if it is called in a tight loop on a fast machine the time of the node can become skewed.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; It can only be used to check the local time of day if the time-zone info of the underlying operating system is properly configured.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&amp;bull; there are 86400 seconds in a day&lt;br /&gt;&amp;bull; there are 365 days in an ordinary year&lt;br /&gt;&amp;bull; there are 366 days in a leap year&lt;br /&gt;&amp;bull; there are 1461 days in a 4 year period&lt;br /&gt;&amp;bull; there are 36524 days in a 100 year period&lt;br /&gt;&amp;bull; there are 146097 days in a 400 year period&lt;br /&gt;&amp;bull; there are 719528 days between Jan 1, 0 and Jan 1, 1970.&lt;/div&gt;&lt;div&gt;以及闰年规则:&lt;/div&gt;&lt;div&gt;&amp;bull; Y is divisible by 4, but not by 100; or&lt;br /&gt;&amp;bull; Y is divisible by 400.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;calendar模块已经废弃或者不建议使用的模块:&lt;/div&gt;&lt;div&gt;&lt;span style="text-decoration: line-through;"&gt;local_time_to_universal_time({Date1, Time1}) -&amp;gt; {Date2, Time2}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="text-decoration: line-through;"&gt;time_difference(T1, T2) -&amp;gt; {Days, Time}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;常用代码&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;strong&gt;erlang:now转本地时间&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;15&amp;gt; calendar:now_to_local_time(erlang:now()).&lt;br /&gt;{{2012,5,17},{14,32,6}}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;erlang:now转世界时间&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;16&amp;gt; calendar:now_to_universal_time(erlang:now()).&lt;br /&gt;{{2012,5,17},{6,33,2}}&lt;br /&gt;17&amp;gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;验证合法的日期&lt;/strong&gt;&lt;/div&gt;20&amp;gt; calendar:valid_date({0,0,0}).&lt;br /&gt;false&lt;br /&gt;21&amp;gt; calendar:valid_date({0,1,0}).&lt;br /&gt;false&lt;br /&gt;22&amp;gt; calendar:valid_date({0,1,1}).&lt;br /&gt;&lt;div&gt;true&lt;/div&gt;26&amp;gt; calendar:valid_date(90,1,10).&amp;nbsp;&lt;br /&gt;&lt;div&gt;true&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;获得本地时间 年 月 日小时 分 秒&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;1&amp;gt;&amp;nbsp; {{Year,Month,Day},{Hour,Min,Second}}=calendar:local_time().&lt;br /&gt;{{2012,5,17},{14,13,14}}&lt;br /&gt;2&amp;gt; b().&lt;br /&gt;Day = 17&lt;br /&gt;Hour = 14&lt;br /&gt;Min = 13&lt;br /&gt;Month = 5&lt;br /&gt;Second = 14&lt;br /&gt;Year = 2012&lt;br /&gt;ok&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;获得世界时间&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;3&amp;gt; calendar:universal_time().&lt;br /&gt;{{2012,5,17},{6,16,27}}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;本地时间转换到世界时间&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;10&amp;gt; calendar:local_time_to_universal_time_dst({{2012,3,12},{3,23,12}}).&lt;br /&gt;[{{2012,3,11},{19,23,12}}]&lt;br /&gt;11&amp;gt; calendar:local_time_to_universal_time_dst({{2012,3,12},{4,23,12}}).&lt;br /&gt;[{{2012,3,11},{20,23,12}}]&lt;br /&gt;12&amp;gt; calendar:local_time_to_universal_time_dst({{2012,3,12},{5,23,12}}).&lt;br /&gt;[{{2012,3,11},{21,23,12}}]&lt;br /&gt;13&amp;gt;&amp;nbsp; calendar:local_time_to_universal_time_dst({{2012,3,12},{15,23,12}}).&lt;br /&gt;[{{2012,3,12},{7,23,12}}]&lt;br /&gt;14&amp;gt;&amp;nbsp; calendar:local_time_to_universal_time_dst({{2012,3,12},{16,23,12}}).&lt;br /&gt;[{{2012,3,12},{8,23,12}}]&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;世界时间转本地时间&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;12&amp;gt; calendar:universal_time_to_local_time({{2012,3,12},{3,23,12}}).&lt;br /&gt;{{2012,3,12},{11,23,12}}&lt;br /&gt;13&amp;gt; calendar:universal_time_to_local_time({{2012,3,12},{5,23,12}}).&lt;br /&gt;{{2012,3,12},{13,23,12}}&lt;br /&gt;14&amp;gt; calendar:universal_time_to_local_time({{2012,3,12},{20,23,12}}).&lt;br /&gt;{{2012,3,13},{4,23,12}}&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;计算是星期几&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;13&amp;gt; calendar:day_of_the_week(1984,5,15).&lt;br /&gt;2&lt;br /&gt;14&amp;gt; calendar:day_of_the_week(2012,5,17).&lt;br /&gt;4&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;计算是否闰年&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;5&amp;gt; calendar:is_leap_year(1990).&lt;br /&gt;false&lt;br /&gt;6&amp;gt; calendar:is_leap_year(2000).&lt;br /&gt;true&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;计算某年某月有多少天&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;7&amp;gt; calendar:last_day_of_the_month(2000,2).&lt;br /&gt;29&lt;br /&gt;8&amp;gt; calendar:last_day_of_the_month(2000,3).&lt;br /&gt;31&lt;br /&gt;9&amp;gt; calendar:last_day_of_the_month(1990,2).&lt;br /&gt;28&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;秒转时间&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;4&amp;gt; calendar:now_to_datetime(erlang:now()).&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;{{2012,5,17},{5,41,24}}&lt;br /&gt;5&amp;gt; calendar:seconds_to_daystime(87400).&amp;nbsp;&amp;nbsp;&lt;br /&gt;{1,{0,16,40}}&lt;br /&gt;6&amp;gt; calendar:seconds_to_daystime(97400).&lt;br /&gt;{1,{3,3,20}}&lt;br /&gt;7&amp;gt; calendar:seconds_to_daystime(80400).&lt;br /&gt;{0,{22,20,0}}&lt;/div&gt;&lt;div&gt;如果没有超过一天可以使用&lt;/div&gt;&lt;div&gt;8&amp;gt; calendar:seconds_to_time(80400).&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;{22,20,0}&lt;br /&gt;9&amp;gt; calendar:seconds_to_time(86400).&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;** exception error: no function clause matching calendar:seconds_to_time(86400) (calendar.erl, line 357)&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;时间转到秒&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;10&amp;gt; calendar:time_to_seconds({22,20,0}).&lt;br /&gt;80400&lt;br /&gt;11&amp;gt; calendar:time_to_seconds({1,{22,20,0}}).&lt;br /&gt;** exception error: no function clause matching calendar:time_to_seconds({1,{22,20,0}}) (calendar.erl, line 390)&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;计算Unix Timestamp&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;timestamp() -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; calendar:datetime_to_gregorian_seconds(erlang:universaltime()).&lt;/div&gt;&lt;div&gt;或者:&lt;/div&gt;&lt;div&gt;timestamp() -&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {M, S, _} = erlang:now(), &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; M * 1000000 + S.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;日期时间格式化&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;16&amp;gt; test:now_to_local_string(erlang:now()).&lt;br /&gt;"2012-05-17T16:14:42.195510+08:00"&lt;br /&gt;17&amp;gt; test:now_to_utc_string(erlang:now()).&amp;nbsp;&lt;br /&gt;"2012-05-17T08:15:26.907466Z"&lt;br /&gt;18&amp;gt; test:timestamp_to_iso(calendar:local_time()).&lt;br /&gt;"20120517T16:27:18"&lt;/div&gt;&lt;div&gt;下面的代码实现上面的时间格式化效果:&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #000000;"&gt;timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}) -&amp;gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008080;"&gt;lists:&lt;/span&gt;&lt;span style="color: #000000;"&gt;flatten(&lt;br/&gt;      &lt;/span&gt;&lt;span style="color: #008080;"&gt;io_lib:&lt;/span&gt;format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~4..0w~2..0w~2..0wT~2..0w:~2..0w:~2..0w&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            [Year, Month, Day, Hour, Minute, Second])).&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;now_to_utc_string({MegaSecs, Secs, MicroSecs}) -&amp;gt;&lt;br/&gt;    {{Year, Month, Day}, {Hour, Minute, Second}} =&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;now_to_universal_time({MegaSecs, Secs, MicroSecs}),&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008080;"&gt;lists:&lt;/span&gt;&lt;span style="color: #000000;"&gt;flatten(&lt;br/&gt;      &lt;/span&gt;&lt;span style="color: #008080;"&gt;io_lib:&lt;/span&gt;format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6..0wZ&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            [Year, Month, Day, Hour, Minute, Second, MicroSecs])).&lt;br/&gt;&lt;br/&gt;now_to_local_string({MegaSecs, Secs, MicroSecs}) -&amp;gt;&lt;br/&gt;    LocalTime = &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;now_to_local_time({MegaSecs, Secs, MicroSecs}),&lt;br/&gt;    UTCTime = &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;now_to_universal_time({MegaSecs, Secs, MicroSecs}),&lt;br/&gt;    Seconds = &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;datetime_to_gregorian_seconds(LocalTime) -&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;datetime_to_gregorian_seconds(UTCTime),&lt;br/&gt;    {{H, M, _}, Sign} = if&lt;br/&gt;                Seconds &amp;lt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;                {&lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;seconds_to_time(-Seconds), &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;}&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;                true -&amp;gt;&lt;br/&gt;                {&lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;seconds_to_time(Seconds), &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;+&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;br/&gt;    end,&lt;br/&gt;    {{Year, Month, Day}, {Hour, Minute, Second}} = LocalTime,&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008080;"&gt;lists:&lt;/span&gt;&lt;span style="color: #000000;"&gt;flatten(&lt;br/&gt;      &lt;/span&gt;&lt;span style="color: #008080;"&gt;io_lib:&lt;/span&gt;format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~4..0w-~2..0w-~2..0wT~2..0w:~2..0w:~2..0w.~6..0w~s~2..0w:~2..0w&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;            [Year, Month, Day, Hour, Minute, Second, MicroSecs, Sign, H, M])).&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;% yyyy-mm-&lt;/span&gt;&lt;span style="color: #008080;"&gt;ddThh:mm:&lt;/span&gt;ss[.sss]{Z|{+|-}&lt;span style="color: #008080;"&gt;hh:&lt;/span&gt;&lt;span style="color: #000000;"&gt;mm} -&amp;gt; {MegaSecs, Secs, MicroSecs}&lt;br/&gt;datetime_string_to_timestamp(TimeStr) -&amp;gt;&lt;br/&gt;    case catch parse_datetime(TimeStr) of&lt;br/&gt;    {&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;EXIT&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;, _Err} -&amp;gt;&lt;br/&gt;        undefined&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    TimeStamp -&amp;gt;&lt;br/&gt;        TimeStamp&lt;br/&gt;    end.&lt;br/&gt;&lt;br/&gt;parse_datetime(TimeStr) -&amp;gt;&lt;br/&gt;    [Date, Time] = &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;tokens(TimeStr, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;T&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br/&gt;    D = parse_date(Date),&lt;br/&gt;    {T, MS, TZH, TZM} = parse_time(Time),&lt;br/&gt;    S = &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;datetime_to_gregorian_seconds({D, T}),&lt;br/&gt;    S1 = &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;datetime_to_gregorian_seconds({{&lt;span style="color: #800080;"&gt;1970&lt;/span&gt;, &lt;span style="color: #800080;"&gt;1&lt;/span&gt;, &lt;span style="color: #800080;"&gt;1&lt;/span&gt;}, {&lt;span style="color: #800080;"&gt;0&lt;/span&gt;, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;}}),&lt;br/&gt;    Seconds = (S - S1) - TZH * &lt;/span&gt;&lt;span style="color: #800080;"&gt;60&lt;/span&gt; * &lt;span style="color: #800080;"&gt;60&lt;/span&gt; - TZM * &lt;span style="color: #800080;"&gt;60&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;    {Seconds &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;div&lt;/span&gt; &lt;span style="color: #800080;"&gt;1000000&lt;/span&gt;, Seconds rem &lt;span style="color: #800080;"&gt;1000000&lt;/span&gt;&lt;span style="color: #000000;"&gt;, MS}.&lt;br/&gt;&lt;br/&gt;% yyyy-mm-dd&lt;br/&gt;parse_date(Date) -&amp;gt;&lt;br/&gt;    [Y, M, D] = &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;tokens(Date, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br/&gt;    Date1 = {list_to_integer(Y), list_to_integer(M), list_to_integer(D)},&lt;br/&gt;    case &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;valid_date(Date1) of&lt;br/&gt;    true -&amp;gt;&lt;br/&gt;        Date1&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    _ -&amp;gt;&lt;br/&gt;        false&lt;br/&gt;    end.&lt;br/&gt;&lt;br/&gt;% &lt;/span&gt;&lt;span style="color: #008080;"&gt;hh:mm:&lt;/span&gt;&lt;span style="color: #000000;"&gt;ss[.sss]TZD&lt;br/&gt;parse_time(Time) -&amp;gt;&lt;br/&gt;    case &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;str&lt;/span&gt;(Time, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Z&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;) of&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;        parse_time_with_timezone(Time)&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    _ -&amp;gt;&lt;br/&gt;        [T | _] = &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;tokens(Time, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Z&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br/&gt;        {TT, MS} = parse_time1(T),&lt;br/&gt;        {TT, MS, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;, &lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;}&lt;br/&gt;    end.&lt;br/&gt;&lt;br/&gt;parse_time_with_timezone(Time) -&amp;gt;&lt;br/&gt;    case &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;str&lt;/span&gt;(Time, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;+&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;) of&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;        case &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;str&lt;/span&gt;(Time, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;) of&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;            false&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        _ -&amp;gt;&lt;br/&gt;            parse_time_with_timezone(Time, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;        end&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    _ -&amp;gt;&lt;br/&gt;        parse_time_with_timezone(Time, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;+&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;    end.&lt;br/&gt;&lt;br/&gt;parse_time_with_timezone(Time, Delim) -&amp;gt;&lt;br/&gt;    [T, TZ] = &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;&lt;span style="color: #000000;"&gt;tokens(Time, Delim),&lt;br/&gt;    {TZH, TZM} = parse_timezone(TZ),&lt;br/&gt;    {TT, MS} = parse_time1(T),&lt;br/&gt;    case Delim of&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;        {TT, MS, -TZH, -TZM}&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;    &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;+&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;        {TT, MS, TZH, TZM}&lt;br/&gt;    end.&lt;br/&gt;&lt;br/&gt;parse_timezone(TZ) -&amp;gt;&lt;br/&gt;    [H, M] = &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;tokens(TZ, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br/&gt;    {[H1, M1], true} = check_list([{H, &lt;/span&gt;&lt;span style="color: #800080;"&gt;12&lt;/span&gt;}, {M, &lt;span style="color: #800080;"&gt;60&lt;/span&gt;&lt;span style="color: #000000;"&gt;}]),&lt;br/&gt;    {H1, M1}.&lt;br/&gt;&lt;br/&gt;parse_time1(Time) -&amp;gt;&lt;br/&gt;    [HMS | T] =  &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;tokens(Time, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br/&gt;    MS = case T of&lt;br/&gt;         [] -&amp;gt;&lt;br/&gt;         &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;         [Val] -&amp;gt;&lt;br/&gt;         list_to_integer(&lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;left(Val, &lt;span style="color: #800080;"&gt;6&lt;/span&gt;, $&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br/&gt;     end,&lt;br/&gt;    [H, M, S] = &lt;/span&gt;&lt;span style="color: #008080;"&gt;string:&lt;/span&gt;tokens(HMS, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br/&gt;    {[H1, M1, S1], true} = check_list([{H, &lt;/span&gt;&lt;span style="color: #800080;"&gt;24&lt;/span&gt;}, {M, &lt;span style="color: #800080;"&gt;60&lt;/span&gt;}, {S, &lt;span style="color: #800080;"&gt;60&lt;/span&gt;&lt;span style="color: #000000;"&gt;}]),&lt;br/&gt;    {{H1, M1, S1}, MS}.&lt;br/&gt;&lt;br/&gt;check_list(List) -&amp;gt;&lt;br/&gt;    &lt;/span&gt;&lt;span style="color: #008080;"&gt;lists:&lt;/span&gt;&lt;span style="color: #000000;"&gt;mapfoldl(&lt;br/&gt;      fun({L, N}, B)-&amp;gt;&lt;br/&gt;      V = list_to_integer(L),&lt;br/&gt;      if&lt;br/&gt;          (V &amp;gt;= &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;and&lt;/span&gt;&lt;span style="color: #000000;"&gt; (V =&amp;lt; N) -&amp;gt;&lt;br/&gt;          {V, B}&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;          true -&amp;gt;&lt;br/&gt;          {false, false}&lt;br/&gt;      end&lt;br/&gt;      end, true, List).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;构造日期字符串&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;% a function to format date/time properly (e.g. &lt;span style="color: #800080;"&gt;09&lt;/span&gt; instead of &lt;span style="color: #800080;"&gt;9&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;return_2columns(X) -&amp;gt;&lt;br/&gt;    case length(X) of&lt;br/&gt;        &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt; -&amp;gt;&lt;br/&gt;            &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;0&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; ++ X&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        _ -&amp;gt;&lt;br/&gt;            X&lt;br/&gt;    end.&lt;br/&gt;&lt;br/&gt;%%% 显然这里可以直接使用 &lt;/span&gt;&lt;span style="color: #008080;"&gt;io_lib:&lt;/span&gt;format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~2..0B&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, [X])&lt;br/&gt;&lt;br/&gt;% returns date/time as a properly formatted string (e.g. &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;01-01-2000 12:12:12&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;get_current_time() -&amp;gt;&lt;br/&gt;    {{Y, M, D}, {H, Mi, S}} = &lt;/span&gt;&lt;span style="color: #008080;"&gt;calendar:&lt;/span&gt;&lt;span style="color: #000000;"&gt;local_time(),&lt;br/&gt;    L = &lt;/span&gt;&lt;span style="color: #008080;"&gt;lists:&lt;/span&gt;&lt;span style="color: #000000;"&gt;map(fun(X) -&amp;gt; &lt;br/&gt;                          X2=integer_to_list(X), &lt;br/&gt;                          return_2columns(X2) &lt;br/&gt;                  end, &lt;br/&gt;                  [Y, M, D, H, Mi, S]&lt;br/&gt;                 ),&lt;br/&gt;    [Y2, M2, D2, H2, Mi2, S2] = L,&lt;br/&gt;    Y2 ++ &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; ++ M2 ++ &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;-&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; ++ D2 ++ &lt;span style="color: #800000;"&gt;"&lt;/span&gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt; ++ H2 ++ &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; ++ Mi2 ++ &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;:&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; ++ S2.&lt;/div&gt;&lt;p&gt;&amp;nbsp;当然下面的代码段也很有可能被用到:&lt;/p&gt;&amp;nbsp;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;day(&lt;span style="color: #800080;"&gt;1&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Mon&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;day(&lt;span style="color: #800080;"&gt;2&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Tue&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;day(&lt;span style="color: #800080;"&gt;3&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Wed&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;day(&lt;span style="color: #800080;"&gt;4&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Thu&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;day(&lt;span style="color: #800080;"&gt;5&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Fri&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;day(&lt;span style="color: #800080;"&gt;6&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sat&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;day(&lt;span style="color: #800080;"&gt;7&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sun&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;&lt;br/&gt;month_to_list(&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Jan&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;2&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Feb&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;3&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Mar&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;4&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Apr&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;5&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;May&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;6&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Jun&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;7&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Jul&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;8&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Aug&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;9&lt;/span&gt;)  -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sep&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;10&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Oct&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;11&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Nov&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;month_to_list(&lt;span style="color: #800080;"&gt;12&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Dec&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;&lt;br/&gt;list_to_month(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Jan&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Feb&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;2&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Mar&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;3&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Apr&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;4&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;May&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;5&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Jun&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;6&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Jul&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;7&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Aug&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;8&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sep&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;9&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Oct&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;10&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Nov&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;11&lt;/span&gt;&lt;span style="color: #008000;"&gt;;&lt;br/&gt;&lt;/span&gt;list_to_month(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Dec&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;) -&amp;gt; &lt;span style="color: #800080;"&gt;12&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt; &lt;/span&gt;&lt;/div&gt;&lt;p&gt;Note:&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;天&lt;/strong&gt;(Day)&lt;/span&gt;这个概念是和时区有关的,使用Unix时间戳计算的时候要考虑到&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;时区差异&lt;/span&gt;&lt;/strong&gt;,比如两个Unix时间戳是否在同一天,一天的起始时间的时间戳,等等;软件多语言版本的时候这个问题特别要关注&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;晚 安 !&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;相关资料:&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[1] 时区&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/%E6%97%B6%E5%8C%BA"&gt;http://zh.wikipedia.org/wiki/%E6%97%B6%E5%8C%BA&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;[2]&amp;nbsp;国家授时中心网络服务器时间发布&amp;nbsp;&lt;a href="http://www.time.ac.cn/stime.asp"&gt;http://www.time.ac.cn/stime.asp&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[3] GMT时间&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/GMT"&gt;http://zh.wikipedia.org/wiki/GMT&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[4] UTC时间&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/%E5%8D%94%E8%AA%BF%E4%B8%96%E7%95%8C%E6%99%82"&gt;http://zh.wikipedia.org/wiki/%E5%8D%94%E8%AA%BF%E4%B8%96%E7%95%8C%E6%99%82&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[5] UNIX时间&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/UNIX%E6%97%B6%E9%97%B4"&gt;http://zh.wikipedia.org/wiki/UNIX%E6%97%B6%E9%97%B4&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[6] 千年虫问题&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/%E5%8D%83%E5%B9%B4%E8%99%AB"&gt;http://zh.wikipedia.org/wiki/%E5%8D%83%E5%B9%B4%E8%99%AB&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[7] 公历&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Gregorian_calendar"&gt;http://en.wikipedia.org/wiki/Gregorian_calendar&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[8] 夏时制&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/%E5%A4%8F%E6%97%B6%E5%88%B6"&gt;http://zh.wikipedia.org/wiki/%E5%A4%8F%E6%97%B6%E5%88%B6&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[9] 日期格式化&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/ISO_8601"&gt;http://en.wikipedia.org/wiki/ISO_8601&lt;/a&gt;&lt;/div&gt;&lt;div&gt;[10] $100&amp;nbsp;&lt;a href="http://zh.wikipedia.org/wiki/100%E7%BE%8E%E5%85%83%E7%BA%B8%E5%B8%81"&gt;http://zh.wikipedia.org/wiki/100%E7%BE%8E%E5%85%83%E7%BA%B8%E5%B8%81&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2506958.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/17/erlang-calendar-date-time.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/09/2491008.html</id><title type="text">Linux/Unix设计思想 读书笔记</title><summary type="text">初识Erlang时感觉怪异的方法命名,写Shell脚本时的恍然大悟，原来一切源头都在《Linux/Unix 涉及思想》</summary><published>2012-05-08T16:04:00Z</published><updated>2012-05-08T16:04:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/09/2491008.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/09/2491008.html"/><content type="html">&lt;div&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;初识Erlang时感觉怪异的方法命名,写Shell脚本时的恍然大悟，原来一切源头都在《Linux/Unix 设计思想》&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;下面是我的读书笔记,按照我自己的理解重新梳理了一下:&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;读书笔记&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&lt;span&gt;尽快建立原型,寻找90%的解决方案，先运行起来再说&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;保持程序的小巧，一次做好一件事情&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span&gt;站在巨人的肩膀上 在原有软件的基础上进行加强和扩展&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;各部分之和大于整体&lt;/li&gt;&lt;li&gt;高效率和可移植性之间往往存在取舍&lt;/li&gt;&lt;li&gt;层次化思考&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;交互界面 往往让我们距离问题的本质更远&lt;/li&gt;&lt;li&gt;尽可能自动化&lt;/li&gt;&lt;li&gt;让每一个程序都成为过滤器所有程序的共有特征就是修改数据而不创造数据&lt;/li&gt;&lt;li&gt;使用小写字母，并保持简短&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;不过书中类似于下面的文字请自行甄别,判断:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;div&gt;&lt;span&gt;也许我们应该提及，大众汽车公司曾经围绕着"小即是美"的概念开展了一次成功的汽车营销活动，并借此销售了数以百万计的汽车；或者想一想主流Unix供应商Sun公司的事例，它的商业战略基于"集中所有资源推出最好的拳头产品"这一思想，或者换句话说，也就是"只做好一件事"的理念。那么，人们对于掌上电脑、无线网络访问和手持视频的兴趣是否与可移植性有关呢？&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;对操作系统来说，华丽的图形界面没有任何意义，除非它能为用户提供所需要的功能。换句话说，内容为王。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span&gt;人们之所以涌向互联网和万维网是为了获得文本内容。&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h1 style="margin-left: 30px;"&gt;参考资料:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;[1]&amp;nbsp;&lt;a href="http://blog.163.com/gogocrazy_li/blog/static/191189147201222252222255/" target="_blank"&gt;《思维之火》之如何识破他在扯蛋（上） &amp;nbsp;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;[2]&amp;nbsp;&lt;a href="http://blog.163.com/gogocrazy_li/blog/static/191189147201222335217809/" target="_blank"&gt;《思维之火》之如何识破他在扯蛋（中） &lt;/a&gt;&lt;/p&gt;&lt;p&gt;[3] &lt;a href="http://blog.163.com/gogocrazy_li/blog/static/19118914720122263112383/" target="_blank"&gt;《思维之火》之如何识破他在扯蛋（下）&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;[4]&amp;nbsp;&lt;a href="http://blog.163.com/gogocrazy_li/blog/static/19118914720122214152249/" target="_blank"&gt;《思维之火》之如何成为一个自由的思考者 &lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012050920311635.jpg" alt="" width="500" height="270" /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2491008.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/09/2491008.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/05/06/erlang-function-call-efficiency.html</id><title type="text">[Erlang 0058] Erlang Function调用效率</title><summary type="text">Erlang方法调用有m:f(a),M:F(a),fun,f(),apply/3几种方法,调用效率如何呢?《Erlang/OTP in Action》和官方文档中都有相关的总结一起看下.</summary><published>2012-05-06T00:51:00Z</published><updated>2012-05-06T00:51:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/05/06/erlang-function-call-efficiency.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/05/06/erlang-function-call-efficiency.html"/><content type="html">&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;Erlang方法调用有m:f(a),M:F(a),fun,f(),apply/3几种方法,调用效率如何呢?《Erlang/OTP in Action》一书中有一个总结我们看下：&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012050608411828.png" alt="" width="600" height="197" /&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; 即模块内调用和模块间的方法调用速度差异不大;要关注一下元编程方式调用(apply调用)要慢的多,除此之外除非是在性能要求特别高的场景否则不必过于在意这点性能差异;这个在官方文档中有大致相同的结果:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;span&gt;Here is an intentionally rough guide to the relative costs of different kinds of calls. It is based on benchmark figures run on Solaris/Sparc:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;Calls to local or external functions (&lt;span&gt;foo()&lt;/span&gt;,&amp;nbsp;&lt;span&gt;m:foo()&lt;/span&gt;) are the fastest kind of calls.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Calling or applying a&lt;strong&gt;&amp;nbsp;fun&lt;/strong&gt;&amp;nbsp;(&lt;span&gt;Fun()&lt;/span&gt;,&amp;nbsp;&lt;span&gt;apply(Fun, [])&lt;/span&gt;) is about&amp;nbsp;&lt;strong&gt;three times&lt;/strong&gt;&amp;nbsp;as expensive as calling a local function.&lt;/li&gt;&lt;li&gt;Applying an exported function (&lt;span&gt;Mod:Name()&lt;/span&gt;,&amp;nbsp;&lt;span&gt;apply(Mod, Name, [])&lt;/span&gt;) is about twice as expensive as calling a fun, or about&amp;nbsp;&lt;strong&gt;six times&lt;/strong&gt;&amp;nbsp;as expensive as calling a local function.&lt;br /&gt;&lt;span style="font-size: 12px; color: #3366ff;"&gt;DocLink:&amp;nbsp;&lt;a href="http://www.erlang.org/doc/efficiency_guide/functions.html"&gt;&lt;span style="color: #3366ff;"&gt;http://www.erlang.org/doc/efficiency_guide/functions.html&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;概念明确&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;对于上面的结论,明确一下上面表中&lt;strong&gt;跨模块调用&lt;/strong&gt;这个概念在Erlang中常用的表达方式:&lt;/div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;In the first form of function calls,&amp;nbsp;&lt;/span&gt;&lt;span&gt;ExprM:ExprF(Expr1,...,ExprN)&lt;/span&gt;&lt;span&gt;, each of&amp;nbsp;&lt;/span&gt;&lt;span&gt;ExprM&lt;/span&gt;&lt;span&gt;&amp;nbsp;and&amp;nbsp;&lt;/span&gt;&lt;span&gt;ExprF&lt;/span&gt;&lt;span&gt;&amp;nbsp;must be an atom or an expression that evaluates to an atom. The function is said to be called by using the&amp;nbsp;&lt;/span&gt;&lt;strong&gt;fully qualified function name&lt;/strong&gt;&lt;span&gt;. This is often referred to as a&amp;nbsp;&lt;/span&gt;&lt;strong&gt;remote&lt;/strong&gt;&lt;span&gt;&amp;nbsp;or&amp;nbsp;&lt;/span&gt;&lt;strong&gt;external function call&lt;/strong&gt;&lt;span&gt;.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px; color: #3366ff;"&gt;DocLink:&amp;nbsp;&lt;a href="http://www.erlang.org/doc/reference_manual/expressions.html#id76190"&gt;&lt;span style="color: #3366ff;"&gt;http://www.erlang.org/doc/reference_manual/expressions.html#id76190&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;速度差异因何而来&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; fun包含或者间接包含了实现了该方法的指针调用不涉及hash-table的查询,apply/3必须要在HashTable中查找funtion对应的Code实现，所以通常比直接调用或者fun调用速度要慢.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;编译时优化&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;在参数个数确定的时候，apply/3的调用会在编译时被优化为m:f(a)形式的external function call.通过一段代码看一下：&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;a() -&amp;gt;&lt;span style="color: #000000;"&gt; &lt;br/&gt;    M=erlang,&lt;br/&gt;    F=now,&lt;br/&gt;    apply(M,F,[]).&lt;br/&gt;&lt;br/&gt;b(M,F,A) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt; &lt;br/&gt;   apply(M,F,A).&lt;br/&gt;&lt;br/&gt;c(M,F) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;   apply(M,F,[a,b,c]).&lt;br/&gt;   &lt;br/&gt;d(M)&lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;   apply(M,do_something,[]).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp; 我们添加to_core参数,看一下编译出来的Core Erlang代码:&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;/&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; =&lt;br/&gt;    %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;33&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; () -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;36&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     call &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;erlang&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;:&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;now&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;         ()&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;b&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;/&lt;span style="color: #800080;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt; =&lt;br/&gt;    %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;38&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (_cor2,_cor1,_cor0) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;39&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     call &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;erlang&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;:&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;apply&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;         (_cor2, _cor1, _cor0)&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;c&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;/&lt;span style="color: #800080;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt; =&lt;br/&gt;    %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;41&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (_cor1,_cor0) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;42&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     call _cor1:_cor0&lt;br/&gt;         (&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;a&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;, &lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;b&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;, &lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;c&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;d&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;/&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt; =&lt;br/&gt;    %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;44&lt;/span&gt;&lt;br/&gt;    &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (_cor0) -&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     %% Line &lt;/span&gt;&lt;span style="color: #800080;"&gt;45&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     call _cor0:&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;do_something&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;         ()&lt;br/&gt; &lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;可以看到在参数个数确定的情况下,apply/3的调用已经都被优化为mfa的调用方式.&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Erlang代码加载自后的调用方式细节需要找资料深入研究一下,估计是在Code Server相关的代码中,待续&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2485589.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/05/06/erlang-function-call-efficiency.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html</id><title type="text">[Erlang 0057] Erlang 排错利器: Erlang Crash Dump Viewer</title><summary type="text">Erlang Crash Dump Viewer真的是排错的天兵神器,还记得我们之前曾经讨论过[Erlang 0013]抓取Erlang进程运行时信息 [Erlang 0012]Erlang Process input queue ,下面是我梳理的"How to interpret the Erlang crash dumps"的文档;</summary><published>2012-04-28T10:02:00Z</published><updated>2012-04-28T10:02:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html"/><content type="html">&lt;p&gt;&amp;nbsp; Erlang Crash Dump Viewer真的是排错的天兵神器,还记得我们之前曾经讨论过&lt;a class="titlelink" href="http://www.cnblogs.com/me-sa/archive/2011/11/06/erlang0013.html"&gt;[Erlang 0013]抓取Erlang进程运行时信息&lt;/a&gt;&amp;nbsp;&lt;a class="titlelink" href="http://www.cnblogs.com/me-sa/archive/2011/11/05/erlang0012.html"&gt;[Erlang 0012]Erlang Process input queue&lt;/a&gt;&lt;span&gt;&amp;nbsp;,下面是我梳理的"How to interpret the Erlang crash dumps"的文档;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;官方地址是:&lt;a href="http://www.erlang.org/doc/apps/erts/crash_dump.html"&gt;http://www.erlang.org/doc/apps/erts/crash_dump.html&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;思维导图地址:http://d.yun.io/Q5fY7b&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;PDF地址:http://d.yun.io/Q5fY7b&lt;/span&gt;&lt;/p&gt;&lt;div id="__ss_12725595" style="width: 1024px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a title="Erlang crash dump" href="http://www.slideshare.net/ligaoren/erlang-crash-dump-12725595" target="_blank"&gt;Erlang crash dump&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/12725595" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="1024" height="1200"&gt;&lt;/iframe&gt;&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;documents&lt;/a&gt; from &lt;a href="http://www.slideshare.net/ligaoren" target="_blank"&gt;ligaoren&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2475556.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2475556.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/04/28/2474892.html</id><title type="text">[Erlang 0056] 用fun在Erlang Shell中编写尾递归 Ⅱ</title><summary type="text">之前研究了一个问题"[Erlang 0050]用fun在Erlang Shell中编写尾递归",一直对这个问题保持着关注;最近在搜索引擎里找到同一个问题,题目足够清晰calling fun() from fun() 它提供了另外一种解决解决方案:Y-combinator!</summary><published>2012-04-28T04:08:00Z</published><updated>2012-04-28T04:08:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2474892.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2474892.html"/><content type="html">&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&amp;nbsp;之前研究了一个问题"&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/03/24/you-win-yourself-zen-this-is-the-50-erlang-article-go-on.html"&gt;[Erlang 0050]用fun在Erlang Shell中编写尾递归&lt;/a&gt;",一直对这个问题保持着关注;最近在搜索引擎里找到同一个问题,题目足够清晰&lt;a href="http://article.gmane.org/gmane.comp.lang.erlang.general/21765"&gt;calling fun() from fun()&lt;/a&gt;&amp;nbsp;它提供了另外一种解决解决方案:Y-combinator!&lt;/span&gt;&lt;/p&gt;&lt;div align="left"&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #808080;"&gt;%%&lt;/span&gt;&lt;span style="color: #808080;"&gt;That's easy, you need the Y-combinator!&lt;/span&gt;&lt;br/&gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;y(M) &lt;/span&gt;-&amp;gt;&lt;span style="color: #000000;"&gt;&lt;br/&gt;     G &lt;/span&gt;= &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (F) -&amp;gt; M(&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(A) -&amp;gt; (F(F))(A) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;     G(G).&lt;br/&gt;&lt;br/&gt;  &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;and&lt;/span&gt; then you define you &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; with a &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;&lt;span style="color: #000000;"&gt; wrapper like so:&lt;br/&gt;&lt;br/&gt;Fac &lt;/span&gt;-&amp;gt; &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (F) -&amp;gt;&lt;br/&gt;           &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (0) -&amp;gt; 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;               (N) &lt;/span&gt;-&amp;gt; N * F(N-1&lt;span style="color: #000000;"&gt;)&lt;br/&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;br/&gt;        &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;and&lt;/span&gt;&lt;span style="color: #000000;"&gt; call it like:&lt;br/&gt;&lt;br/&gt;(y(Fac))(&lt;/span&gt;5&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;120&lt;/div&gt;&lt;p&gt;&lt;span style="font-family: Consolas; font-size: 12px;"&gt;不错吧,不过我们的目标是在shell里面直接实现尾递归,所以要动手简单改造一下&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; Y=&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(F) -&amp;gt;&lt;br/&gt;1&amp;gt;     G = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(T) -&amp;gt;&lt;br/&gt;1&amp;gt;         F(&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(X) -&amp;gt; (T(T))(X) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;1&amp;gt;     &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;&lt;/span&gt;1&amp;gt;     G(G) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;2&amp;gt;  &lt;br/&gt;2&amp;gt; Fac = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (F) -&amp;gt;&lt;br/&gt;2&amp;gt;           &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (0) -&amp;gt; 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;2&amp;gt;               (N) -&amp;gt; N * F(N-1&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;2&amp;gt;           &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;br/&gt;2&amp;gt;       &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;3&amp;gt; &lt;br/&gt;3&amp;gt; (Y(Fac))(5&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;120&lt;br/&gt;4&amp;gt; Fib = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(F) -&amp;gt;&lt;br/&gt;4&amp;gt;           &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(0) -&amp;gt; 0&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;4&amp;gt;              (1) -&amp;gt; 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;4&amp;gt;              (N) -&amp;gt; F(N-1) + F(N-2&lt;span style="color: #000000;"&gt;) &lt;br/&gt;&lt;/span&gt;4&amp;gt;           &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;br/&gt;4&amp;gt;       &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;5&amp;gt; &lt;br/&gt;5&amp;gt; (Y(Fib))(8&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;21&lt;br/&gt;6&amp;gt; &lt;/div&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Consolas;"&gt;问题还没有结束,对于两个参数的怎么办呢?Y函数比较直观,可以修改为:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;6&amp;gt; Y2=&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(F) -&amp;gt;&lt;br/&gt;6&amp;gt;     G = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(T) -&amp;gt;&lt;br/&gt;6&amp;gt;         F(&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(Y, Z) -&amp;gt; (T(T))(Y, Z) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;6&amp;gt;     &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br/&gt;&lt;/span&gt;6&amp;gt;     G(G) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;7&amp;gt;  Func2=&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(F)-&amp;gt;&lt;br/&gt;7&amp;gt;           &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(X,Y) &lt;span style="color: #0000ff;"&gt;when&lt;/span&gt; Y&amp;lt;1000 -&amp;gt;io:format("~p,",[X+Y]), F(Y,X+&lt;span style="color: #000000;"&gt;Y);  &lt;br/&gt;&lt;/span&gt;7&amp;gt;           (X,Y) -&amp;gt;&lt;span style="color: #000000;"&gt; done    &lt;br/&gt;&lt;/span&gt;7&amp;gt;                &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;br/&gt;7&amp;gt;        &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;8&amp;gt; &lt;br/&gt;8&amp;gt; (Y2(Func2))(0,1&lt;span style="color: #000000;"&gt;).&lt;br/&gt;&lt;/span&gt;1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,done&lt;/div&gt;&lt;p&gt;&lt;span style="font-family: Consolas;"&gt;&amp;nbsp;&lt;span style="font-size: 12px;"&gt; 当然多个参数我们可以使用apply mfa的方式来处理多个参数的情况.同时Y方法也可以放在user_default里面方便后续使用.实践之后说一点理论吧,这种解决方案是使用了Y combinator可能最近你已经频繁接触到这个名字,比如在&lt;a href="http://news.baidu.com/ns?word=Y+combinator&amp;amp;tn=news&amp;amp;from=news&amp;amp;cl=2&amp;amp;rn=20&amp;amp;ct=1"&gt;IT新闻&lt;/a&gt;,比如在&amp;lt;&amp;lt;&lt;a href="http://book.douban.com/subject/6021440/"&gt;黑客与画家&lt;/a&gt;&amp;gt;&amp;gt;,它本身是&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 12px;"&gt;一个数学概念,那么我们从维基百科开始:&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;英文维基&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Consolas;"&gt;Fixed-point combinator &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Fixed-point_combinator"&gt;http://en.wikipedia.org/wiki/Fixed-point_combinator&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Consolas;"&gt;Y combinator: &lt;a href="http://rosettacode.org/wiki/Y_combinator"&gt;http://rosettacode.org/wiki/Y_combinator&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Tahoma;"&gt;&lt;strong&gt;中文维基&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Tahoma;"&gt;不动点组合子 &lt;a href="http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%8A%A8%E7%82%B9%E7%BB%84%E5%90%88%E5%AD%90"&gt;http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%8A%A8%E7%82%B9%E7%BB%84%E5%90%88%E5%AD%90&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Consolas;"&gt;不动点 &lt;/span&gt;&lt;a href="http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%8A%A8%E7%82%B9"&gt;http://zh.wikipedia.org/wiki/%E4%B8%8D%E5%8A%A8%E7%82%B9&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Tahoma;"&gt;&amp;lambda;演算 &lt;a href="http://zh.wikipedia.org/wiki/%E6%97%A0%E7%B1%BB%E5%9E%8B_lambda_%E6%BC%94%E7%AE%97"&gt;http://zh.wikipedia.org/wiki/%E6%97%A0%E7%B1%BB%E5%9E%8B_lambda_%E6%BC%94%E7%AE%97&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family: arial, sans-serif;"&gt;&lt;span style="font-size: 11px; line-height: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Tahoma;"&gt; 我们理顺一下里面的逻辑关系,从&lt;strong&gt;不动点&lt;/strong&gt;开始:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Tahoma;"&gt; 在数学中，函数的不动点或定点是指被这个函数映射到其自身一个点.例如,定义在实数上的函数f,f(x)=x&lt;sup&gt;2&lt;/sup&gt;-3x+4则2是函数f的一个不动点，因为f(2)=2.也不是每一个函数都具有不动点。例如定义在实数上的函数,f(x)=x+1就没有不动点。因为对于任意的实数，x永远不会等于x+1。用画图的话来说，不动点意味着点(x,f(x))在直线y=x上，或者换句话说，函数f的图像与那根直线有共点。上例f(x)=x+1的情况是，这个函数的图像与那根直线是一对平行线.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;span style="font-family: Tahoma;"&gt;&amp;nbsp;我用wolframalpha.com绘制了&lt;/span&gt;f(x)=x&lt;sup&gt;2&lt;/sup&gt;-3x+4的函数图:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012042812010916.png" alt="" /&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-family: Tahoma;"&gt;&amp;nbsp; &lt;span style="font-size: 12px;"&gt;&amp;nbsp;接下来我们看&lt;strong&gt;不动点组合子&lt;/strong&gt;(Fixed-point combinator,或不动点算子)是计算其他函数的一个不动点的高阶函数.函数 f 的不动点是一个值 x 使得 f(x) = x.例如,0 和 1 是函数 f(x) = x2 的不动点,因为 02 = 0 而 12 = 1.鉴于一阶函数(在简单值比如整数上的函数)的不动点是个一阶值,高阶函数 f 的不动点是另一个函数 g 使得 f(g) = g.那么,不动点算子是任何函数 fix 使得对于任何函数 f 都有f(fix(f)) = fix(f).不动点组合子允许&lt;strong&gt;定义匿名的递归函数&lt;/strong&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;   然后接下来是Y combinator(Y组合子)在无类型 lambda 演算中众所周知的(可能是最简单的)不动点组合子叫做 Y 组合子.它是 Haskell B. Curry 发现的,定义为&lt;/span&gt;&lt;/p&gt;&lt;dl&gt;&lt;dd&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;= &amp;lambda;f.(&amp;lambda;x.f (x x)) (&amp;lambda;x.f (x x)) &amp;nbsp;%%用一个例子函数&lt;strong&gt;g&lt;/strong&gt;来展开它，我们可以看到上面这个函数是怎么成为一个不动点组合子的&lt;/span&gt;&lt;/dd&gt;&lt;dd&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;g = (&amp;lambda;f.(&amp;lambda;x . f (x x)) (&amp;lambda;x . f (x x))) g&lt;/span&gt;&lt;/dd&gt;&lt;dd&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;g = (&amp;lambda;x. g (x x)) (&amp;lambda;x . g (x x)) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%%&amp;lambda;f 的 &amp;beta;-归约 - 应用主函数于 g&lt;/span&gt;&lt;/dd&gt;&lt;dd&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;g = (&amp;lambda;y. g (y y)) (&amp;lambda;x . g (x x)) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;%%&amp;alpha;-转换 - 重命名约束变量&lt;/span&gt;&lt;/dd&gt;&lt;dd&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;g = g ((&amp;lambda;x. g (x x)) (&amp;lambda;x . g (x x))) &amp;nbsp; &amp;nbsp; %%&amp;lambda;y 的 &amp;beta;-归约 - 应用左侧函数于右侧函数&lt;/span&gt;&lt;/dd&gt;&lt;dd&gt;&lt;span style="font-size: 12px;"&gt;&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;g = g (&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;g) &amp;nbsp; %%&lt;strong&gt;Y&lt;/strong&gt;&amp;nbsp;的定义&amp;nbsp;&lt;/span&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&amp;nbsp; 这个!?在编程语言里面怎么实现呢?看一下&lt;a href="http://rosettacode.org/wiki/Y_combinator#Erlang"&gt;http://rosettacode.org/wiki/Y_combinator&lt;/a&gt;&amp;nbsp;这里罗列了大多数语言对Y combinator的实现,比如C#版本:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;delegate&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;Func&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&amp;gt; Recursive(Recursive recursive);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;void&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;Main()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Func&amp;lt;Func&amp;lt;Func&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&amp;gt;, Func&amp;lt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&amp;gt;&amp;gt;, Func&amp;lt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&amp;gt;&amp;gt; Y =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f =&amp;gt; ((Recursive)(g =&amp;gt; (f(x =&amp;gt; g(g)(x)))))((Recursive)(g =&amp;gt; f(x =&amp;gt; g(g)(x))));&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;fac = Y(f =&amp;gt; x =&amp;gt; x &amp;lt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;?&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;: x * f(x -&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;var&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;fib = Y(f =&amp;gt; x =&amp;gt; x &amp;lt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;? x : f(x -&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;) + f(x -&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(fac(&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(fib(&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #c81efa; font-family: Consolas; font-size: small;"&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;));&lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-family: Consolas; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&lt;span style="font-size: 12px;"&gt; 不过注意一下Erlang版本的实现,上面提供了另外一种实现方式(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 12px;"&gt;只不过在下面这种实现中,怎么使用多个参数呢?):&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;Eshell V5.9  (abort with ^&lt;span style="color: #000000;"&gt;G)&lt;br/&gt;&lt;/span&gt;1&amp;gt; Y = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(M) -&amp;gt; (&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(X) -&amp;gt; X(X) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;)(&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (F) -&amp;gt; M(&lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(A) -&amp;gt; (F(F))(A) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;2&amp;gt; Fac = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (F) -&amp;gt;&lt;br/&gt;2&amp;gt;           &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt; (0) -&amp;gt; 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;2&amp;gt;               (N) -&amp;gt; N * F(N-1&lt;span style="color: #000000;"&gt;)&lt;br/&gt;&lt;/span&gt;2&amp;gt;           &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;br/&gt;2&amp;gt;       &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;3&amp;gt; (Y(Fac))(5&lt;span style="color: #000000;"&gt;).       &lt;br/&gt;&lt;/span&gt;120&lt;br/&gt;4&amp;gt; &lt;br/&gt;4&amp;gt; Fib = &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(F) -&amp;gt;&lt;br/&gt;4&amp;gt;           &lt;span style="color: #0000ff;"&gt;fun&lt;/span&gt;(0) -&amp;gt; 0&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;4&amp;gt;              (1) -&amp;gt; 1&lt;span style="color: #000000;"&gt;;&lt;br/&gt;&lt;/span&gt;4&amp;gt;              (N) -&amp;gt; F(N-1) + F(N-2&lt;span style="color: #000000;"&gt;) &lt;br/&gt;&lt;/span&gt;4&amp;gt;           &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;br/&gt;4&amp;gt;       &lt;span style="color: #0000ff;"&gt;end&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;br/&gt;#Fun&lt;/span&gt;&amp;lt;erl_eval.6.111823515&amp;gt;&lt;br/&gt;5&amp;gt; (Y(Fib))(8).     &lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;span style="font-family: verdana, Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-size: 14px; line-height: 20px; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 12px;"&gt;&amp;nbsp; 沿着Y Combinator这个线索,可以找到更多的资料,&lt;cite&gt;&lt;span&gt;&lt;br /&gt;&lt;a href="http://www.dreamsongs.com/Files/WhyOfY.pdf"&gt;[PDF] &amp;nbsp;The Why of Y - Dreamsongs&lt;/a&gt;&lt;/span&gt;&lt;a href="http://www.dreamsongs.com/Files/WhyOfY.pdf"&gt;&amp;nbsp;&lt;/a&gt;&amp;nbsp;&lt;/cite&gt;&lt;button id="gbpwm_0" title="Recommend this page"&gt;&lt;/button&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;[1]&amp;nbsp;&lt;a href="http://bc.tech.coop/blog/070611.html"&gt;Y Combinator in Erlang&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size: 12px;"&gt;[2]&amp;nbsp;&lt;a href="http://www.cnblogs.com/me-sa/articles/2471418.html"&gt;Deriving the Y Combinator in Erlang&lt;/a&gt;&amp;nbsp; (原文已经被墙,这是我拷贝出来的副本)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://d.yun.io/public/getcontent/shorturl/c0Bowu" alt="" width="353" height="235" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2474892.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2474892.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/me-sa/archive/2012/04/28/2474408.html</id><title type="text">Disk is Tape, Flash is Disk</title><summary type="text">今天遇到一副来自Google的图罗列了常见操作的时间损耗,见高清大图..</summary><published>2012-04-27T16:04:00Z</published><updated>2012-04-27T16:04:00Z</updated><author><name>坚强2002</name><uri>http://www.cnblogs.com/me-sa/</uri></author><link rel="alternate" href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2474408.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2474408.html"/><content type="html">&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; &amp;nbsp;今天遇到一副来自Google的图罗列了常见操作的时间损耗,见高清大图:&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012042723530718.png" alt="" width="573" height="430" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&lt;br /&gt;&amp;nbsp; 这张图让我想到之前在使用Redis时看到Jim Gray那句被坊间流传许久的话:"&lt;span style="color: #000000; font-family: 'times new roman', times;"&gt;&lt;strong&gt;Tape is &lt;span style="color: #ff0000;"&gt;Dead&lt;/span&gt;, Disk is Tape, Flash is Disk, RAM Locality is King&lt;/strong&gt;&lt;/span&gt;".(磁带已死,磁盘是新磁带,闪存是新磁盘,随机存储器局部性是为王道.) 这句话的原始出处在此:&amp;nbsp;&lt;a href="http://www.signallake.com/innovation/Flash_is_Good.pdf"&gt;http://www.signallake.com/innovation/Flash_is_Good.pdf&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;这里有一篇中文解读:&amp;nbsp;&lt;a href="http://www.infoq.com/cn/news/2008/07/ram-is-disk"&gt;http://www.infoq.com/cn/news/2008/07/ram-is-disk&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;div&gt;&lt;span style="font-size: 13px;"&gt;&lt;a href="http://research.microsoft.com/~Gray/JimGrayHomePageSummary.htm"&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;Jim Gray&lt;/a&gt;在过去40年中对技术发展有过巨大的贡献，&amp;ldquo;内存是新的硬盘，硬盘是新的磁带&amp;rdquo;是他的名言。&amp;ldquo;实时&amp;rdquo;Web应用不断涌现，达到海量规模的系统越来越多，这种后浪推前浪的发展模式对软硬件又有何影响？&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.tbray.org/ongoing/"&gt;Tim Bray&lt;/a&gt;早在网格计算成为热门话题之前，就&lt;a href="http://www.tbray.org/ongoing/When/200x/2006/05/24/On-Grids"&gt;讨论过&lt;/a&gt;以RAM和网络为中心的硬件结构的优势，可以用这种硬件建立比磁盘集群速度更快的RAM集群。&lt;/span&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;span style="font-size: 13px;"&gt;对于数据的随机访问，内存的速度比硬盘高几个数量级（即使是最高端的磁盘存储系统也只是勉强达到1,000次寻道/秒）。其次， 随着数据中心的网络速度提高，访问内存的成本更进一步降低。通过网络访问另一台机器的内存比访问磁盘成本更低。就在我写下这段话的时候，Sun的 Infiniband产品线中有一款具备9个全互联非阻塞端口交换机，每个端口的速度可以达到30Gbit/sec！Voltaire产品的端口甚至更多；简直不敢想象。（如果你想了解这类超高性能网络的最新进展，请关注Andreas Bechtolsheim在Standford开设的课程。）&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size: 13px;"&gt;Tim还指出Jim Gray的名言中后半句所阐述的真理：&amp;ldquo;对于随机访问，硬盘慢得不可忍受；但如果你把硬盘当成磁带来用，它吞吐连续数据的速率令人震惊；它天生适合用来给以RAM为主的应用做日志（logging and journaling）。&amp;rdquo;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 13px;"&gt;时间闪到几年之后的今天，我们发现硬件的发展趋势在RAM和网络领域势头不减，而在硬盘领域则止步不前。Bill McColl提到用于并行计算的&lt;a href="http://www.computingatscale.com/?p=54"&gt;海量内存系统已经出现&lt;/a&gt;：&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: 13px;"&gt;内存是新的硬盘！硬盘速度提高缓慢，内存芯片容量指数上升，in-memory软件架构有望给各类数据密集的应用带来数量级的性能提升。小型机架服务器（1U、2U）很快就会具备T字节、甚至更大量的内存，这将会改变服务器架构中内存和硬盘之间的平衡。硬盘将成为新的磁带，像磁带一样作为顺序存储介质使用（硬盘的顺序访问相当快速），而不再是随机存储介质（非常慢）。这里面有着大量的机会，新产品的性能有望提高10倍、100倍。&lt;br /&gt;&lt;br /&gt;Dare Obsanjo指出&lt;a href="http://www.25hoursaday.com/weblog/2008/05/23/SomeThoughtsOnTwittersAvailabilityProblems.aspx"&gt;如果不把这句真言当回事，会带来什么样的恶劣后果&lt;/a&gt;&amp;mdash;&amp;mdash; 也就是Twitter正面临的麻烦。论及Twitter的内容管理，Obsanjo说，&amp;ldquo;如果一个设计只是简单地反映了问题描述，你去实现它就会落入磁盘 I/O的地狱。不管你用Ruby on Rails、Cobol on Cogs、C++还是手写汇编都一样，读写负载照样会害死你。&amp;rdquo;换言之，应该把随机操作推给RAM，只给硬盘留下顺序操作。&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;div id="__ss_3804062" style="width: 425px;"&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="width: 425px;"&gt;&lt;span style="font-size: 13px; color: #999999;"&gt;下面是来自slideshare的两份资料(不显示多刷几遍):&lt;/span&gt;&lt;/div&gt;&lt;div style="width: 425px;"&gt;&lt;hr /&gt;&lt;span style="font-size: 13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="width: 425px;"&gt;&lt;span style="font-size: 13px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a title="Redis -- Memory as the New Disk" href="http://www.slideshare.net/tim.lossen.de/redis-memory-as-the-new-disk" target="_blank"&gt;Redis -- Memory as the New Disk&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/3804062" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="425" height="355"&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;div style="padding: 5px 0 12px;"&gt;&lt;span style="font-size: 13px;"&gt; View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/tim.lossen.de" target="_blank"&gt;Tim Lossen&lt;/a&gt; &lt;/span&gt;&lt;/div&gt; &lt;/div&gt;&lt;div id="__ss_8959849" style="width: 425px;"&gt;&lt;span style="font-size: 13px;"&gt; &lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a title="What every data programmer needs to know about disks" href="http://www.slideshare.net/iammutex/what-every-data-programmer-needs-to-know-about-disks" target="_blank"&gt;What every data programmer needs to know about disks&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/8959849" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="425" height="355"&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;div style="padding: 5px 0 12px;"&gt;&lt;span style="font-size: 13px;"&gt; View more &lt;a href="http://www.slideshare.net/thecroaker/death-by-powerpoint" target="_blank"&gt;PowerPoint&lt;/a&gt; from &lt;a href="http://www.slideshare.net/iammutex" target="_blank"&gt;iammutex&lt;/a&gt; &lt;/span&gt;&lt;/div&gt; &lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 13px;"&gt;深入理解计算机系统&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;回顾一下计算机的经典教材《深入理解计算机系统》中对高速缓存的讲解,书中是从最简单的hello程序切入的:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2012/17329/2012042723574376.png" alt="" width="687" height="400" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; hello程序的机器指令最初是存放在磁盘上的,当程序加载时,它们被复制到主存;当处理器运行程序时,指令又从主存复制到处理器.相似地,数据串&amp;ldquo;hello, world\n&amp;rdquo;初始时在磁盘上,然后复制到主存,最后从主存上复制到显示设备.&lt;/span&gt;&lt;span style="font-size: 13px;"&gt;根据机械原理,较大的存储设备要比较小的存储设备运行得慢,而快速设备的造价远高于同类的低速设备.例如,一个典型系统上的磁盘驱动器可能比主存大1000倍,但是对处理器而言,从磁盘驱动器上读取一个字的时间开销要比从主存中读取的开销大1000万倍.&lt;/span&gt;&lt;span style="font-size: 13px;"&gt;针对这种处理器与主存之间的差异,系统设计者采用了更小,更快的存储设备,即高速缓存存储器(简称高速缓存),作为暂时的集结区域,用来存放处理器近期可能会需要的信息.&lt;/span&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp; &amp;nbsp;在处理器和一个又大又慢的设备(例如主存)之间插入一个更小更快的存储设备(例如高速缓存)的想法已经成为了一个普遍的观念.实际上,每个计算机系统中的存储设备都被组织成了一个存储器层次结构,上图所示.在这个层次结构中,从上至下,设备变得访问速度越来越慢,容量越来越大,并且每字节的造价也越来越便宜.寄存器文件在层次结构中位于最顶部,也就是第0级或记为L0.这里我们展示的是三层高速缓存L1到L3,占据存储器层次结构的第1层到第3层.主存在第4层,以此类推&lt;/span&gt;&lt;span style="font-size: 13px;"&gt;存储器层次结构的主要思想是一层上的存储器作为低一层存储器的高速缓存.因此,寄存器文件就是L1的高速缓存,L1是L2的高速缓存,L2是L3的高速缓存,L3是主存的高速缓存,而主存又是磁盘的高速缓存.在某些具有分布式文件系统的网络系统中,本地磁盘就是存储在其他系统中磁盘上的数据的高速缓存.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;晚安!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/17329/2012042800023511.jpg" alt="" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 13px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/me-sa/aggbug/2474408.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/me-sa/archive/2012/04/28/2474408.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
