免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2090 | 回复: 1
打印 上一主题 下一主题

[其他] 从 UNIX 开发人员的角度了解 Erlang [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-01-18 10:38 |只看该作者 |倒序浏览
简介
如果您是 UNIX 开发人员或系统管理员,很可能会有自己喜欢的一套工具。您可能喜欢 Perl、Python、sed 和 awk 或 Ruby。也可能喜欢 Java™ 或 C++。当您熟悉了一套工具之后,可能不愿意再花时间学习新的语言。必须有强有力的理由证明这么做是值得的。学习 Erlang 就有足够强有力的理由。在本文中,我会解释为什么应该学习 Erlang 以及如何开始。
多核系统的时代已经到来了,但是我们还没有准备好。许多语言依赖于脆弱的并发机制,比如线程和共享的状态,甚至是更糟的全局锁(它导致一个线程只能在单一核上执行)。典型的 *nix 服务器有 24 个核。编程人员很容易编写出过于复杂且容易出错的线程化代码;也很容易编写出只使用 24 核系统上的一个内核的代码,无法充分利用整个 CPU。对于这个问题,一个解决方案是使用专门针对伸缩设计的函数语言。Erlang 没有可变的状态,这是它与 *nix 专业人员使用的大多数流行语言的重要差异。另外,并发是它的固有特性。实际上,其他许多语言都是围绕对象构建的,而 Erlang 是围绕进程构建的。因为由语言(而不是操作系统)控制并发机制,所以生成数千甚至数百万个进程是很普通的。在 Erlang 中,处理问题的方式不一样,这恰恰可以解决当今的计算难题。
交互式的 Erlang shell
喜欢命令行的人会很喜欢 Erlang 的交互式 shell。可以通过交互式 shell 输入表达式、编译代码以及与进程进行通信。它的设计相当优雅,让我觉得就像是在管理使用 Lights Out Management 卡的 *nix 系统和先进的虚拟化系统一样。假设您已经在系统上安装了 Erlang。安装 Erlang 之后,会在路径中找到 "erl"。输入 "erl" 时,会进入交互式提示,可以在这里输入命令。

交互式 shell:部分 A
lion% erlErlang R14B (erts-5.8.1) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.8.1  (abort with ^G)1>

要想看到帮助菜单,则应该执行下面的 help 命令。注意,每个表达式必须用点号结束,告诉解释器可以执行该表达式了。另外,可以随时输入 "q().",参见下面的帮助菜单输出。

交互式 shell:帮助输出
                                Eshell V5.8.1  (abort with ^G)1> help().** shell internal commands **b()        -- display all variable bindingse(N)       -- repeat the expression in query <N>f()        -- forget all variable bindingsf(X)       -- forget the binding of variable Xh()        -- historyhistory(N) -- set how many previous commands to keepresults(N) -- set how many previous command results to keepcatch_exception(B) -- how exceptions are handledv(N)       -- use the value of query <N>rd(R,D)    -- define a recordrf()       -- remove all record informationrf(R)      -- remove record information about Rrl()       -- display all record informationrl(R)      -- display record information about Rrp(Term)   -- display Term using the shell's record informationrr(File)   -- read record information from File (wildcards allowed)rr(F,R)    -- read selected record information from file(s)rr(F,R,O)  -- read selected record information with options** commands in module c **bt(Pid)    -- stack backtrace for a processc(File)    -- compile and load code in <File>cd(Dir)    -- change working directoryflush()    -- flush any messages sent to the shellhelp()     -- help infoi()        -- information about the systemni()       -- information about the networked systemi(X,Y,Z)   -- information about pid <X,Y,Z>l(Module)  -- load or reload modulelc([File]) -- compile a list of Erlang modulesls()       -- list files in the current directoryls(Dir)    -- list files in directory <Dir>m()        -- which modules are loadedm(Mod)     -- information about module <Mod>memory()   -- memory allocation informationmemory(T)  -- memory allocation information of type <T>nc(File)   -- compile and load code in <File> on all nodesnl(Module) -- load module on all nodespid(X,Y,Z) -- convert X,Y,Z to a Pidpwd()      -- print working directoryq()        -- quit - shorthand for init:stop()regs()     -- information about registered processesnregs()    -- information about all registered processesxm(M)      -- cross reference check a moduley(File)    -- generate a Yecc parser** commands in module i (interpreter interface) **ih()       -- print help for the i moduletrue2>

输入这些命令并观察它们的作用,这对学习 Erlang 有很大的意义。在实际编写代码时,需要牢记的是,Erlang 中的状态是不可变的,所以在设置变量时会看到下面的输出,这可能让您很吃惊:

交互式 shell:部分 B
Eshell V5.8.1  (abort with ^G)1> Var = 1.12> Var = 2.** exception error: no match of right hand side value 23>

当然,在学习新语言时总是应该先研究一下 "Hello World" 示例:

交互式 shell:部分 C
4> io:format("Hello World~n").Hello Worldok

在全面的 Erlang 课程中还要讨论很多东西,但这里最终只提供了一个常用的数据类型列表示例:

交互式 shell:部分 D
5> List = [1,2,3].[1,2,3]6> [Head|Tail] = List.[1,2,3]7> Head.1

在这个示例中,使用模式匹配提取列表的开头和结尾部分。模式匹配在 Erlang 中起到很大的作用。
编写并编译 Erlang 模块
用 Erlang 编写应用程序需要编写模块,而不只是编写交互式 shell 中看到的表达式。首先注意开发环境。如果打算进行很多 Erlang 开发工作,可以考虑使用带 Erlide 插件的 Eclipse 或 Emacs。在使用 Erlang 进行轻量级编程时,vim 表现得很好。

带 Erlide 插件的 Eclipse

如果使用带 Erlide 的 Eunit 这样的 IDE,它会在编写模块代码时自动将代码编译为 beam 文件,这相当方便。也可以在 Erlang 交互式解释器中或通过 erlc 命令行编译器执行编译。下面是一个简单的模块,它将模块代码编译为 beam 文件:

fingerprint.erl
%% This is a module that gets the operating system type-module(fingerprint).-export([get_os/0]).get_os ()->    os:cmd("uname").

要想以交互方式编译模块代码并运行它,则应该再次运行 erl

以交互方式编译模块
lion% erl                                    Erlang R14B (erts-5.8.1) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]Eshell V5.8.1  (abort with ^G)1> c(fingerprint).{ok,fingerprint}2> fingerprint:get_os/0       module_info/0  module_info/1  2> fingerprint:get_os()."Darwin\n"3> q().ok

如果在 shell 中直接列出文件,那么您会看到已经创建了 fingerprint.beam 文件。也可以通过运行以下命令创建这个 beam 文件:
lion% erlc fingerprint.erl

使用 EUnit 对 Erlang 进行单元测试
如果您在编写 Erlang 代码,很可能是要构建高可用的系统。如果是这样,一定要从一开始就注意细节并为代码编写单元测试。对于前面的模块,相应的测试像下面这样:

EUnit 示例
%% This is a module that gets the operating system type-module(fingerprint_with_test).-include_lib("eunit/include/eunit.hrl").-export([get_os/0]).get_os ()->    os:cmd("uname").get_os_test ()->    get_os().

要点是,要想用 EUnit 测试模块,则需要包含头文件(如上所示)并按照 "_test" 模式命名函数。如果这样做,则会自动导出所有测试函数并通过下面的代码运行它们。

以交互方式编译和测试 EUnit
Eshell V5.8.1  (abort with ^G)1> c(fingerprint_with_test).{ok,fingerprint_with_test}2> fingerprint_with_test:test().  Test passed.ok3>

使用 Erlang 作为脚本语言或从命令行执行它
还应该注意的是,可以在脚本模式下运行 Erlang,这样就不需要先编译代码。为此,需要运行 R11B4 或更高版本的 Erlang 副本。我们可以略微修改前面的示例,通过添加脚本解释器行和主函数把它变成脚本:

以交互方式编译和测试 EUnit
#!/usr/local/bin/escriptget_os ()->    os:cmd("uname").main(_) ->    io:format("OS Platform: ~p~n", [get_os()]).

下面是输出:
lion% chmod +x fingerprint.escriptlion% ./fingerprint.escript  OS Platform: "Darwin\n"

最后,与 Perl 或 Ruby 一样,还可以在命令行中编写单行脚本。可以将同一个示例编写为单行脚本,如下所示:
lion% erl -eval 'io:format("OS Platform: ~p~n", [os:cmd("uname")])' -noshell -s init stopOS Platform: "Darwin\n"

分布式计算变得很容易:Mac OS X 和 Ubuntu 之间的远程消息传递
掌握了一些基础知识之后,我们就可以开始做真正有意思的事情了,比如构建相互通信的进程的集群。因为有 Location Transparency 特性,所以很容易在单一系统上测试集群,然后将它转移到大型分布式集群上,其中的系统可以位于世界各地!在下面的示例中,我在 Ubuntu(通过虚拟机)和 Mac OS X 上启动 Erlang,只用几行代码就可以远程地运行代码。注意,对于这个示例,假设已经正确地配置了本地 DNS 和防火墙设置(如果有的话)。
首先,在 Ubuntu 和 OS X 节点上都启动 Erlang:
mac% erl -name mac -setcookie test

ubuntu% erl -name mac -setcookie test

完成上述操作之后,就可以从 OS X 机器建立通信,通过调用 nodes 函数验证是否可以看到远程节点:
(mac@lion.local)1> net_adm:ping('ubuntu@ubuntu.localdomain').pong(mac@lion.local)2> nodes(). ['ubuntu@ubuntu.localdomain']

现在,可以执行任意代码:
(mac@lion.local)15> rpc:call('ubuntu@ubuntu.localdomain', os, cmd, ['uname -a']). "Linux ubuntu.local 2.6.35-24-generic #42-Ubuntu SMP Thu Dec 2 01:41:57 UTC 2010 i686 GNU/Linux\n"

很容易看出 Erlang 是多么强大,使用 Erlang 进行进程间通信是多么容易。尽管这是一个非常简单的示例,但您应该能够通过它体会到 Erlang 的强大之处。

结束语
本文讨论了使用 Erlang 的理论和实践,但是还有很多东西要学习。在今后几年,使用 Erlang 编写的大型生产系统会急剧增加。最近的一篇 Harvard Business Review 文章指出,“短缺” 是促进创新的首要因素。现在短缺的是在处理高度灵活且可伸缩的系统方面的经验丰富的专业人员。您现在应该努力成为 Erlang 语言专家,这会为您提供强大的竞争优势。
如果您有兴趣进一步了解 Erlang,我给出了以下建议。最好阅读一本或所有的 Erlang 书籍,有三本刚出版的书可供选择。这些书都不错。另外,您可以学习 tryerlang.org 上的交互式教程(请参阅 “参考资料”)。最后,还可以试试一些正在发展的 Erlang 项目,比如 CouchDB、RabbitMQ 和 Ejabbrd。


http://www.ibm.com/developerworks/cn/aix/library/au-learning_erlang/index.html


论坛徽章:
0
2 [报告]
发表于 2014-09-08 10:27 |只看该作者
这个讲的不错,谢谢楼主!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP