Archive

Archive for April, 2007

写出正确的尾递归代码

April 29th, 2007 :: jackyz

你可能早已耳闻,在 erlang 中,循环变成了递归。

你很可能常常看见这样的代码,并因为它是来自于 erlang 官方的文档 getting start with erlang 而觉得这样的代码,可能就是传说中的尾递归。

  1. -module(tut1).
  2. -export([fac/1]).
  3.  
  4. fac(1) ->
  5.     1;
  6. fac(N) ->
  7.     N * fac(N - 1).

没错,一个函数自己调用自己,这就是递归。但,这真的就是传说中可以通过编译优化得“和循环一样快,没有额外开销”的尾递归么?递归和尾递归,是否存在差异呢?

我们可以做一个试验。
Read more…

study

【转】Erlang 里面使用Remote shell

April 29th, 2007 :: jackyz

原文地址:avindev.javaeye.com
原文作者:AvinDev

今天无意中发现这个功能。。。

ejabberd.jabber.ru

在下载的 getting_started-5.0.1.pdf 那里也有这个topic:《Advanced Shell Usage – Job Control Mode》,不知道为何官方html格式的文档那里消失了。

简单来说是这样,比如节点 foo@192.168.0.2 启动了一个daemon

  1. erl -name foo@192.168.0.2 -setcookie 123456 -noshell -noinput ...

注:即,无shell,无输入,可以理解为以无界面的方式启动。
注:选项 setcookie 是指定 magic cookie ,这个参数也可以在文件中指定。这是 erlang 的“要么就都没有,要么就全权控制”的安全机制,两个 erlang 的 node 如果需要通讯,必须要有相同的 magic cookie。也就是说,你如果知道目标机器的 magic cookie 你就可以远程管理它。

如果要管理它,可以这样:

  1. # ./start.sh -name bar@192.168.0.3 -setcookie 123456
  2. Erlang (BEAM) emulator version 5.5.4 [source] [async-threads:0] [hipe] [kernel-poll:false]
  3.  
  4. Eshell V5.5.4 (abort with ^G)
  5. (bar@192.168.0.3)1>
  6. User switch command
  7. --> h
  8. c [nn] - connect to job
  9. i [nn] - interrupt job
  10. k [nn] - kill job
  11. j - list all jobs
  12. s - start local shell
  13. r [node] - start remote shell
  14. q - quit erlang
  15. ? | h - this message
  16. --> j
  17. 1* {shell,start,[init]}
  18. --> r 'foo@192.168.0.2'
  19. --> j
  20. 1 {shell,start,[init]}
  21. 2* {'foo@192.168.0.2',shell,start,[]}
  22. --> c 2
  23. Eshell V5.5.4 (abort with ^G)
  24. (foo@192.168.0.2)1> nodes().
  25. ['bar@192.168.0.3']

比用什么rpc的方便多了
btw:Control+G无法在win下的shell里面使用~

注: Control+G 在 windows 下的 erl 中的确不能用,但在 werl (另一个 shell 界面)中可以照样用,windows 下 werl 的热键与文档保持高度一致。

study

【转】Erlang 字符编码模块: iconv

April 29th, 2007 :: jackyz

原文地址:avindev.javaeye.com
原文作者:AvinDev

在Erlang中,要处理字符串编码的转换,可以使用iconv,目前CEAN的发行版本,ejabberd和iconv模块里面都有iconv的库,但是都无法正常运行(提示版本不兼容),但是在ejabberd的安装包可以使用。经过比较,发现是 erl.exe,erlexec.dll,beam.dll 这三个启动程序的问题,ejabberd 的是 V5.5.2.2,而 CEAN1.2 和ErlangOTP R11B4 都是 V5.5.4,可能两个版本跟iconv的c port不兼容。

下面就以ejabberd的erlang版本来说明:

首先启动port

  1. 1> iconv:start().
  2. {ok,<0.30.0>}
  3. 2> iconv:convert("gbk", "utf-8", "你好")
  4. "浣犲ソ"

Windows下控制台编码为gbk,这里将“你好”编码为UTF8后输出,显示乱码,可以用io:format解决:

  1. 3> io:format("~w~n", [iconv:convert("gbk", "utf-8", "你好")]).
  2. [228,189,160,229,165,189]
  3. ok

反过来流程是一样的:

  1. 4> iconv:convert("utf-8", "gbk", [228,189,160,229,165,189]).
  2. "你好"

要解决在Erlang发行版下使用的问题,估计要重新编译iconv的port。有谁有更好的方法,欢迎提出。

注:貌似 N 多的 c port 代码在 cean 版本中都有问题,上次试验 linux 下的 cean yaws 也出了一个 ddll 的包不兼容的问题。而自己从源代码编译 erlang 又巨慢巨痛苦。苦恼啊。

study

【转】erlang module pg2

April 29th, 2007 :: jackyz

原文地址:avindev.javaeye.com
原文作者:AvinDev

《轻松实现可伸缩性,容错性,和负载平衡的大规模多人在线系统》一文里面对“Erlang的分布式进程组(Distributed Named Process Groups)”大吹特吹,就是说的pg2这个module。文档那里虽然写了支持分布式节点,但是并没有说如何如何,只提供了一个join(Name, Pid)。

看了一下openpoker的源码,原来很简单,对于连接上的node,用 which_groups() 多调用几次就可以同步过来了:

主节点先创建一个Group:

  1. (foo@localhost)1> pg2:create(group).
  2. ok
  3. (foo@localhost)2> pg2:get_members(group).
  4. []
  5. (foo@localhost)3> pg2:join(group, self()).
  6. ok
  7. (foo@localhost)4> pg2:get_members(group).
  8. [<0.35.0>]

其他节点先连上主节点,然后调用pg2:which_groups().

  1. (bar@localhost)1> net_adm:ping('foo@localhost').
  2. pong
  3. (bar@localhost)2> pg2:which_groups().
  4. []
  5. (bar@localhost)3> pg2:which_groups().
  6. [group]
  7. (bar@localhost)4> pg2:join(group, self()).
  8. ok

已经加入了:

  1. (foo@localhost)5> pg2:get_members(group).
  2. [<4835.35.0>,<0.35.0>]

使用就是那么简单。但是在pg2的底层实现上,使用了ets,global等模块,下次继续研究。

注:正如它的名称所暗示的 pg2 可以用于管理成组 process 的场景,如:每一个 game session 是一个 process ,由这些 process 形成一个 group ,那么你可以通过这个 group 获取 session 的数目(eg. 在线人数),即便你的 session counter process 死掉,那么在它被自动恢复的时候,可以连上 group 并从中找回 session 数目。

study

【转】使用target_system进行erlang应用的发行

April 29th, 2007 :: jackyz

原文地址:avindev.javaeye.com
原文作者:Avindev

好久之前捣鼓过的东西,怕忘记了,记录一下。

一个简单实现了OTP的Server:echoline,一个Helloworld级别的OTP应用,目录结构如下:

  1. ./src/echoline_app.erl
  2. ./src/echoline_sup.erl
  3. ./src/echoline_server.erl
  4. ./src/tcp_server.erl
  5. ./ebin/echoline_app.app
  6. ./priv/
  7. ./include/
  8. ./echoline_rel.rel
  9. ./Emakefile

这是一个普通的Erlang应用,可以直接使用 erl -make 来编译, Emakefile 内容如下:

  1. {'src/*', [debug_info,{i,'include'},{outdir,'ebin'}]}.

echoline_app.app 内容如下:

  1. {application, echoline_app,   
  2.   [{description, "Echoline Server"}, 
  3.    {vsn, "1"}, 
  4.    {modules, [echoline_app, echoline_sup, echoline_server, tcp_server]}, 
  5.    {registered, []}, 
  6.    {applications, [kernel, stdlib, sasl]}, 
  7.    {mod, {echoline_app,[]}} 
  8.   ]}.

但是这个应用仅仅只能在安装了Erlang的环境下启动。这时候可以这样:
Read more…

study

站点恢复,数据保持完整

April 29th, 2007 :: jackyz

经历了一次服务器莫名奇妙的down机——vps无法启动——恢复失效——彻底死菜——漫长重装——以及数据恢复的过程。无比郁闷。

好在总算都恢复了,好在数据都没丢。汗。

misc

加了Erlang代码的语法加亮,show一下

April 16th, 2007 :: jackyz

今天下午花了一点时间,给 WP 装了一个 CoolCode 的 PlugIn 。

然后 Hack PEAR 的 Text/Highlight 以增加 Erlang 的语法加亮规则(得到 ERLANG.php)

然后再打开 CoolCode 的代码,加上 Erlang 的选项。我们就得到这样的效果。

下载: tut1.erl
  1. -module(tut1).
  2. -export([fac/1]).
  3.  
  4. fac(1) ->
  5.     1;
  6. fac(N) ->
  7.     N * fac(N - 1).

当然了,损失是没法直接使用 TinyMCE 的编辑器了。不过我觉得代价是值得的,能加亮显示 Erlang 的代码,大大提高我们这个 Erlang 主题站点的效果。 :D :D

完整的示例可以参考这里

misc

【转】Simple Dynamic Record Access

April 16th, 2007 :: Sander

原文地址:Programming Experiments
原文作者:Brian Olsen

There is one thing I hate about Erlang, and it is records. It is not so much that the syntax is annoying (yet I am getting used to it), but you cannot use that syntax for dynamic field access; records are a compile-time feature.

So, without using Yariv’s Smerl for something like this, I opted for a simpler solution. Records are tuples after all, and you can get record information in a list. So, you can use these two facts to create a function to get the field you specify. Not anything stellar, but for dynamic record access, it works:

  1. find(Item, List) ->
  2.  find_(Item, List, 1).
  3. find_(Item, [], _) -> not_found;
  4. find_(Item, [H|T], Count) ->
  5.  case H of
  6.   Item ->
  7.    Count;
  8.   _ ->
  9.    find_(Item, T, Count+1)
  10.  end.
  11.  
  12. get_rec_value(Key, Rec, RecordInfo) ->
  13.  case find(Key, RecordInfo) of
  14.   not_found ->
  15.    undefined;
  16.   Num ->
  17.    element(Num+1, Rec)
  18.  end.

I couldn’t find something like “lists:find/2″, so I implemented my own. But the main function is “get_rec_value/3″. So you do this:

  1. 1> rd(person, {id, name, email}).
  2. 2> get_rec_value(name, #person{name="Brian"}, record_info(fields, person)).
  3. "Brian"

For fun, I also did setting record value.

  1. set_rec_value(Key, Value, Rec, RecordInfo) ->
  2.  RecList = tuple_to_list(Rec),
  3.  case find(Key, RecordInfo) of
  4.   not_found ->
  5.    Rec;
  6.   Num ->
  7.    List1 = lists:sublist(RecList, Num),
  8.    List2 = lists:sublist(RecList, Num+2, length(RecList)),
  9.    tuple_to_list(List1 ++ [Value] ++ List2)
  10.  end.
  1. 3> set_rec_value(email, "c", #person{name="Brian", id="1", email="b"}, record_info(fields, person)).

I know this stuff looks really simple, but since I thought this was a bit of a nuisance, the fact that I cannot access records without hardcoding the values, something needed to be written.

Did I miss something though? I’d like to know. Please comment. :)

在 Comment 中, Philip Robinson 提供了解决这一问题的另一种方法

他的方案是通过 EMP1 (Erlang Macro Processor v1) 在编译期解决这一问题。

[本文由 Sander 收集,Jackyz 对此进行了编辑(增加了原文链接和原文作者)]

jackyz: 对于我来说,好像并不觉得 Record 是一个多大的问题,呵呵。 :D

study

CEAN安装的Yaws如何启动?

April 13th, 2007 :: jackyz

最近被 CEAN 迷住了,能直接安装 Erlang ,省掉了漫长的编译过程。而且,大量 Package 可以随需安装,简直方便得不得了。不过,毕竟不是各个安装包本身。小问题总是有的。这时候,就需要 hack in 了。

一个严重的问题是 CEAN 弄下来的 Yaws 貌似不能正常的启动。忙活了半天,连 Yaws 都用不了,兴奋的输入 yaws:start(). 会返回给你若干错误,伤害劳动人民的感情啊。没关系,稍微进行一下深入的研究,我们就能找到办法。

Read more…

study

目前支持Erlang语法的开发环境

April 12th, 2007 :: jackyz

看到有人谈及开发环境。ok,我们就来盘点一下目前市面上能够见到的,支持 Erlang 语法的 IDE/Editor ,其中,IDE有:

1 加拿大的 CaoYuan (华人哦)开发的 ErlyBird (for NetBeans)

2 大名鼎鼎的 ErlIDE (for Eclipse)

Editor有:

1 Emacs

2 Vim

3 JEdit

目前就知道这么多了,其他人补充下吧。

我现在用的环境是 editplus + erlangconsole 呵呵,谁让我的机器太破呢,连 JEdit 都嫌慢。没办法了,没有语法加亮,没有函数OutLine,慢慢也习惯了,好像也不觉得缺啥。 :D

start