April 29th, 2007 :: jackyz
你可能早已耳闻,在 erlang 中,循环变成了递归。
你很可能常常看见这样的代码,并因为它是来自于 erlang 官方的文档 getting start with erlang 而觉得这样的代码,可能就是传说中的尾递归。
- -module(tut1).
- -export([fac/1]).
-
- fac(1) ->
- 1;
- fac(N) ->
- N * fac(N - 1).
没错,一个函数自己调用自己,这就是递归。但,这真的就是传说中可以通过编译优化得“和循环一样快,没有额外开销”的尾递归么?递归和尾递归,是否存在差异呢?
我们可以做一个试验。
Read more…
study
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
- erl -name foo@192.168.0.2 -setcookie 123456 -noshell -noinput ...
注:即,无shell,无输入,可以理解为以无界面的方式启动。
注:选项 setcookie 是指定 magic cookie ,这个参数也可以在文件中指定。这是 erlang 的“要么就都没有,要么就全权控制”的安全机制,两个 erlang 的 node 如果需要通讯,必须要有相同的 magic cookie。也就是说,你如果知道目标机器的 magic cookie 你就可以远程管理它。
如果要管理它,可以这样:
- # ./start.sh -name bar@192.168.0.3 -setcookie 123456
- Erlang (BEAM) emulator version 5.5.4 [source] [async-threads:0] [hipe] [kernel-poll:false]
-
- Eshell V5.5.4 (abort with ^G)
- (bar@192.168.0.3)1>
- User switch command
- --> h
- c [nn] - connect to job
- i [nn] - interrupt job
- k [nn] - kill job
- j - list all jobs
- s - start local shell
- r [node] - start remote shell
- q - quit erlang
- ? | h - this message
- --> j
- 1* {shell,start,[init]}
- --> r 'foo@192.168.0.2'
- --> j
- 1 {shell,start,[init]}
- 2* {'foo@192.168.0.2',shell,start,[]}
- --> c 2
- Eshell V5.5.4 (abort with ^G)
- (foo@192.168.0.2)1> nodes().
- ['bar@192.168.0.3']
比用什么rpc的方便多了
btw:Control+G无法在win下的shell里面使用~
注: Control+G 在 windows 下的 erl 中的确不能用,但在 werl (另一个 shell 界面)中可以照样用,windows 下 werl 的热键与文档保持高度一致。
study
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> iconv:start().
- {ok,<0.30.0>}
- 2> iconv:convert("gbk", "utf-8", "你好").
- "浣犲ソ"
Windows下控制台编码为gbk,这里将“你好”编码为UTF8后输出,显示乱码,可以用io:format解决:
- 3> io:format("~w~n", [iconv:convert("gbk", "utf-8", "你好")]).
- [228,189,160,229,165,189]
- ok
反过来流程是一样的:
- 4> iconv:convert("utf-8", "gbk", [228,189,160,229,165,189]).
- "你好"
要解决在Erlang发行版下使用的问题,估计要重新编译iconv的port。有谁有更好的方法,欢迎提出。
注:貌似 N 多的 c port 代码在 cean 版本中都有问题,上次试验 linux 下的 cean yaws 也出了一个 ddll 的包不兼容的问题。而自己从源代码编译 erlang 又巨慢巨痛苦。苦恼啊。
study
April 29th, 2007 :: jackyz
原文地址:avindev.javaeye.com
原文作者:AvinDev
《轻松实现可伸缩性,容错性,和负载平衡的大规模多人在线系统》一文里面对“Erlang的分布式进程组(Distributed Named Process Groups)”大吹特吹,就是说的pg2这个module。文档那里虽然写了支持分布式节点,但是并没有说如何如何,只提供了一个join(Name, Pid)。
看了一下openpoker的源码,原来很简单,对于连接上的node,用 which_groups() 多调用几次就可以同步过来了:
主节点先创建一个Group:
- (foo@localhost)1> pg2:create(group).
- ok
- (foo@localhost)2> pg2:get_members(group).
- []
- (foo@localhost)3> pg2:join(group, self()).
- ok
- (foo@localhost)4> pg2:get_members(group).
- [<0.35.0>]
其他节点先连上主节点,然后调用pg2:which_groups().
- (bar@localhost)1> net_adm:ping('foo@localhost').
- pong
- (bar@localhost)2> pg2:which_groups().
- []
- (bar@localhost)3> pg2:which_groups().
- [group]
- (bar@localhost)4> pg2:join(group, self()).
- ok
已经加入了:
- (foo@localhost)5> pg2:get_members(group).
- [<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
April 29th, 2007 :: jackyz
原文地址:avindev.javaeye.com
原文作者:Avindev
好久之前捣鼓过的东西,怕忘记了,记录一下。
一个简单实现了OTP的Server:echoline,一个Helloworld级别的OTP应用,目录结构如下:
- ./src/echoline_app.erl
- ./src/echoline_sup.erl
- ./src/echoline_server.erl
- ./src/tcp_server.erl
- ./ebin/echoline_app.app
- ./priv/
- ./include/
- ./echoline_rel.rel
- ./Emakefile
这是一个普通的Erlang应用,可以直接使用 erl -make 来编译, Emakefile 内容如下:
- {'src/*', [debug_info,{i,'include'},{outdir,'ebin'}]}.
echoline_app.app 内容如下:
- {application, echoline_app,
- [{description, "Echoline Server"},
- {vsn, "1"},
- {modules, [echoline_app, echoline_sup, echoline_server, tcp_server]},
- {registered, []},
- {applications, [kernel, stdlib, sasl]},
- {mod, {echoline_app,[]}}
- ]}.
但是这个应用仅仅只能在安装了Erlang的环境下启动。这时候可以这样:
Read more…
study
April 29th, 2007 :: jackyz
经历了一次服务器莫名奇妙的down机——vps无法启动——恢复失效——彻底死菜——漫长重装——以及数据恢复的过程。无比郁闷。
好在总算都恢复了,好在数据都没丢。汗。
misc
April 16th, 2007 :: jackyz
今天下午花了一点时间,给 WP 装了一个 CoolCode 的 PlugIn 。
然后 Hack PEAR 的 Text/Highlight 以增加 Erlang 的语法加亮规则(得到 ERLANG.php)
然后再打开 CoolCode 的代码,加上 Erlang 的选项。我们就得到这样的效果。
- -module(tut1).
- -export([fac/1]).
-
- fac(1) ->
- 1;
- fac(N) ->
- N * fac(N - 1).
当然了,损失是没法直接使用 TinyMCE 的编辑器了。不过我觉得代价是值得的,能加亮显示 Erlang 的代码,大大提高我们这个 Erlang 主题站点的效果。
完整的示例可以参考这里。
misc
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:
- find(Item, List) ->
- find_(Item, List, 1).
- find_(Item, [], _) -> not_found;
- find_(Item, [H|T], Count) ->
- case H of
- Item ->
- Count;
- _ ->
- find_(Item, T, Count+1)
- end.
-
- get_rec_value(Key, Rec, RecordInfo) ->
- case find(Key, RecordInfo) of
- not_found ->
- undefined;
- Num ->
- element(Num+1, Rec)
- 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> rd(person, {id, name, email}).
- 2> get_rec_value(name, #person{name="Brian"}, record_info(fields, person)).
- "Brian"
For fun, I also did setting record value.
- set_rec_value(Key, Value, Rec, RecordInfo) ->
- RecList = tuple_to_list(Rec),
- case find(Key, RecordInfo) of
- not_found ->
- Rec;
- Num ->
- List1 = lists:sublist(RecList, Num),
- List2 = lists:sublist(RecList, Num+2, length(RecList)),
- tuple_to_list(List1 ++ [Value] ++ List2)
- end.
- 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 是一个多大的问题,呵呵。
study
April 13th, 2007 :: jackyz
最近被 CEAN 迷住了,能直接安装 Erlang ,省掉了漫长的编译过程。而且,大量 Package 可以随需安装,简直方便得不得了。不过,毕竟不是各个安装包本身。小问题总是有的。这时候,就需要 hack in 了。
一个严重的问题是 CEAN 弄下来的 Yaws 貌似不能正常的启动。忙活了半天,连 Yaws 都用不了,兴奋的输入 yaws:start(). 会返回给你若干错误,伤害劳动人民的感情啊。没关系,稍微进行一下深入的研究,我们就能找到办法。
Read more…
study
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,慢慢也习惯了,好像也不觉得缺啥。
start
Recent Comments