论坛首页 综合技术版 FP

一门天生就能损害人眼视力的语言->Erlang

浏览 20936 次
该帖已经被评为精华帖
作者 正文
时间:2008-04-05
1.Erlang的历史

我不说太多,只想说Erlang是一门比Java还古老的程序语言,不信请google.


2.支持Erlang的IDE与编辑器

2.1 emacs

官方首推emacs编辑器,我的Ubuntu上也装了个emacs。
没有目录文件浏览窗口,快捷键再多用起来也是别扭,甭提在10来个文件之间来回穿梭啦。
按<Alt+W>、<Ctrl+Y>再怎么熟都没原先按<Ctrl+C>、<Ctrl+V)爽,
最可恨的是滚动鼠标滑轮竟然在emacs无效,非得要按住鼠标左键才能去拉动emacs编辑窗口的下拉条。
(也许是我错了,要是各位有使用emacs的特殊技巧可以指点一下)

当然,我现在不用emacs,只在很少的情况下才开一下。


2.2 ErlyBird

ErlyBird是JavaEye上的dcaoyuan大叔写的软件(要是不到35岁,下次改叫dcaoyuan老兄),
要说ErlyBird是NetBeans上的Erlang插件吗,也不全对,
反正你要是从http://sourceforge.net/project/showfiles.php?group_id=192439
把ErlyBird下下来装好也得60M左右的硬盘空间。

dcaoyuan大叔最好在国内站点也找个放软件的网站,从sourceforge上下软件真是龟速,
我下了少说也有10次,试了几天才下下来,差一点就没耐性啦。

还有ErlyBird在建索引那段时间真的得缩短啦,半小时也能折腾人的,
另外ErlyBird并不是采用Erlang语言的官方编译器,我不知道是不是dcaoyuan大叔自个实现了一个编译器,
反正可视化语法错误提示信息跟官方编译器不一样,
不用官方编译器也有坏处,每次Erlang语言有变动了,就得拼命追赶,就像eclipse一样,总是慢半拍。

比如在ErlyBird中像 “-module(m,['A','B']).”这样的语法认为是错语的,但官方编译器却是没问题的,
dcaoyuan大叔也许没怎么看Erlang语言的官方编译器实现,官方编译器实现总是提供最新的语法支持,
就像NetBeans内置了javac一样,搞IDE的人只要专心搞IDE就行啦,编译器留给其他人去搞,
只要编译器提供接口就行。

Erlang/OTP本身也提供了很多分析源码的工具像:Parsetools、Syntax_Tools其实可以直接利用的。


当然,我现在也没用ErlyBird,我只试了几次,但ErlyBird实在太占内存啦,
开起来要100多M,打开几个Erlang源码文件后没过多久就能飙到300多M,
再怎么点“强制GC”那个按钮,系统监视器中看到的进程占用的内存还是往上飙。
我的本本才512M,自认为比曾经工作时用过的32M内存机子强上无数倍了,
没想到开起ErlyBird没过多久就不能干其他事啦!

最后还是希望ErlyBird越做越好,要是我还在研究Erlang,我想我会支持使用ErlyBird的。



2.3 Erlide

Erlide听说是一个受到爱立信公司资助的基于eclipse的Erlang插件,
我也装了,还用了两个星期,毛病一堆,时不是crash一下,没折了就重启eclipse,
有时重启eclipse看到加载到Erlide时就死翘翘了,好,把工作空间先清空再说,
你想在源代码上加点注释写点心得体会,它非得要你写英文,否则来个不支技的字符集,瀑布汗。。。

要不是看在它能在我的机子上跑起来,比emacs凑合,否则用过一次就扔了。



2.4 Bluefish Editor

我现在一直在用Bluefish Editor看Erlang代码,
Windows时代EditPlus是我的最爱,可惜把Windows扔了后,来到了Ubuntu的世界,
只能为EditPlus找个替代品,Bluefish Editor本身不支持Erlang语言的语法高亮,
我只好自己参照emacs与Erlide的颜色搭配在Bluefish Editor上为Erlang配置语法高亮,
具体效果请看我前面发过的图。


总结:
支持Erlang的IDE目前没有稳定一点的,都还处在幼儿时期,用户体验可以用“很差”来形容。
普通的直接支持Erlang语法高亮的编辑器我看到只有emacs(要另下插件),
其他的没有Erlang语法高亮的编辑器根本就不能用,除非自己手动配置,
否则面对黑压压的一片代码只有超人才会看。
   
0 请登录后投票
时间:2008-04-05
3.Erlang里的注释(Comments)语法

现代大多数流行的语言都支持两种注释风格:单行注释、块注释
对于单行注释,在C/C++/Java中以“//”开头,在Erlang里以“%”开头,
表面上看只用一个字符“%”比使用两个“/”字符更省空间,当然,源代码级别是省了空间,但这点空间微乎其微,
源代码级别的单行注释毕竟是少数,更多的是块注释,
加上源代码经编译后注释根本就不存在啦(除非有特殊需求),所以空间问题也就谈不上。

接着看看人工录入一个“%”字符与录入两个“/”字符所花的时间(各位不妨自己体会一下),
请看看你电脑上的键盘布局,录入一个“%”字符要先按<Shift>键对吧,
当你要成功录入一个“%”字符时是不是动用了两只手,有时一不小心就变成了“5”或者“$”等等,
你再试试录入两个“/”字符,想想你平时是不是总是用右手敲注释,再看看“/”字符在键盘上的位置是不是跟你右手很近?
是的,没错,录入两个“/”字符真的比录入一个“%”字符更快,更准确。

看到这,你可别认为我在钻牛角尖,语言的每一个细节设计都很讲究的,要充分考虑到用户的感受。


好的,接着说块注释,
很遗憾,Erlang语言已变迁到5.6这样的版本啦,还是没有块注释,
有时候你想注释一段20来行的小代码,你都得一个“%”字符一个“%”字符的敲入,
这种最基本的语法功能都还没有,用户体验怎一个“差”字能形容。



4.Erlang语言所使用的字符集

Erlang在语言设计的层次就声明它就使用ISO-8859-1(Latin-1)字符集,
ISO-8859-1字符集能表示的字符范围很小,仅仅使用了Unicode的前256个字符编码(0x0000到0x00FF),
现在Unicode又加入了增补字符集,编码范围已变成了0x0000到0x10FFFF。

而Java语言在设计之初,就充分考虑到了国际化问题,一开始就支持Unicode,
还随着Unicode的变化而变化,即使Unicode编码范围超过了16位,
Java语言为了向后兼容在不改变原来char类型的情况下,
通过代码点(code points)的方式全面支持Unicode增补字符集。

Erlang要想成为下一个Java,一开始设计的时候就要考虑到各个国家的不同情况,
要是我想输出中文信息,现在Erlang还做不到,虽然现在据说有第三方库支持Unicode,
但我认为字符集这种东西本身就是应该在语言层次支持的,不应该用第三方库来扩展,
试想一下你为了输出个中文每次都得先调用个函数把中文转换到内部编码那是多麻烦的一件事?

那现在Erlang要想在语言层次支持Unicode难不难呢?
我也没具体答案,不过我可以说说我能想像到的。

首先,要支持Unicode,Erlang语言规范得改,
比如:补充说明哪些字符能组成标识符、数字,哪些是空白字符等等各类词法规则。

然后写编译器那些人就头痛了,要先考虑是否要向后兼容,
考虑好了,动手改实现代码,从词法分析开始(参见erl_scan.erl文件),
这下好,以前只从256个字符编码中逐个或逐段的手工判断
哪些能组成atom(要是你不明白atom是什么,你就简单当它是一个常量就行了),
哪些是变量,哪些是数字,哪些是空白,哪些是控制字符?
现在呢,从256个字符编码猛一跳,变成了1114111(0x10FFFF)个字符编码,想着都恐怖。

更可怕的是以前变量与atom的区分是以大写字母开头来判断的,
大写字母一跳出ISO-8859-1就不再是A-Z这么简单了。。。

词法分析搞定后,到了代码生成阶段啦,这时又得考虑生成目标文件的内部编码了,
以前内部用8位表示一个字符,现在要支持Unicode,8位肯定是不行的了,
改吧,把目标文件的格式重新定义,目标文件的格式变了,运行时系统也得跟着改吧。。。

哦,还有怪异的Bit Strings和Binaries也很让人头痛的。。。


最后,写标准库、核心库的人也跟着改代码,因为用双引号括起来的字符串实际上是个List,
很多内置函数(BIFs)像length、hd、tl等等都是针对List的,现在要支持Unicode啦总得改改吧,
不改的话一个中文的长度是1,那就闹笑话了。


在国际化方面,Java的确是很多语言的榜样,
国内听说还有个“易语言”,汉语编程?不知是不是钱多了搞这东西,
把Java语言的关建字换成中文,Javac内部再多加个中文-英文关建字对照表,编译时做一下转换,
就变成了一个“超级易语言”,连保存".java"文件都能用中文。



好,今天有空就说到这,下回没事做了再继续(还有很多想说的)。
   
0 请登录后投票
时间:2008-04-05
握手握手~`

Vim 有下拉屏幕的快捷键,Emacs 应该也有。
FP 在实际应用方面,真的很多。计算机科学方面的那些就不提了,说点“亲切的”。知道 .Net 的垃圾收集器是怎么来的吗?先用 Lisp 写了再转成 C++ 得来的。当然,FP 语言自身的性能也是越来越变态(尤以 Haskell 为甚)。像很多人所热衷的类似服务器、数据库、操作系统等“大型软件”,有很多 FP 写的此类应用。
你说的 Erlang 在语法设计还有一些细节方面的问题,其实我也在暗自偷着乐。这也是我不打算宣传 Erlang 的原因。不过作为世界上极少数支持 PI 演算的语言之一,如果处于并发性能考虑,需要用 Erlang 的话,还是得迁就它。
PS: 要不要考虑加入我们愉快的 Vim 大家庭?:)

哦,对了,Erlang 的编译器实现是非常难读懂的,看过《现代编译原理》的话会知道这一点,但那本书译地又不咋地。而且关于 PI 演算的模拟和优化资料严重欠缺,中文资料==无。我连 Haskell 实现都没勇气一看,还是 Scheme 之类的解释器(或者虚拟机)看着比较顺心。
   
0 请登录后投票
时间:2008-04-06
emacs 磨练一下还是不错的,我现在就用emacs写 erlang/scheme这些程序 ,erlware有个erlang的增强版的erlang-mode,挺好用的
   
0 请登录后投票
时间:2008-04-06
看着这样的代码就头晕,还谈得上什么生产力。。。。。。。
   
0 请登录后投票
时间:2008-04-06
lichray 写道
握手握手~`

Vim 有下拉屏幕的快捷键,Emacs 应该也有。
FP 在实际应用方面,真的很多。计算机科学方面的那些就不提了,说点“亲切的”。知道 .Net 的垃圾收集器是怎么来的吗?先用 Lisp 写了再转成 C++ 得来的。当然,FP 语言自身的性能也是越来越变态(尤以 Haskell 为甚)。像很多人所热衷的类似服务器、数据库、操作系统等“大型软件”,有很多 FP 写的此类应用。
你说的 Erlang 在语法设计还有一些细节方面的问题,其实我也在暗自偷着乐。这也是我不打算宣传 Erlang 的原因。不过作为世界上极少数支持 PI 演算的语言之一,如果处于并发性能考虑,需要用 Erlang 的话,还是得迁就它。
PS: 要不要考虑加入我们愉快的 Vim 大家庭?:)

哦,对了,Erlang 的编译器实现是非常难读懂的,看过《现代编译原理》的话会知道这一点,但那本书译地又不咋地。而且关于 PI 演算的模拟和优化资料严重欠缺,中文资料==无。我连 Haskell 实现都没勇气一看,还是 Scheme 之类的解释器(或者虚拟机)看着比较顺心。


先用 Lisp 写了再转成 C++ 得来的---这句话是路边社消息么?
   
0 请登录后投票
时间:2008-04-06
c/c++又能好到哪里去呢?
你觉得这种代码就不损伤视力?
template<class R, class T,
    class B1, class B2, class B3, class B4, class B5, class B6,
    class A1, class A2, class A3, class A4, class A5, class A6, class A7>
    _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
    BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
{
    typedef _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6> F;
    typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
    return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
}

// 7

template<class R, class T,
    class B1, class B2, class B3, class B4, class B5, class B6, class B7,
    class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
    _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
    BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
    typedef _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
    typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
    return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
}

template<class R, class T,
    class B1, class B2, class B3, class B4, class B5, class B6, class B7,
    class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
    _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
    BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
    typedef _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
    typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
    return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
}

// 8

template<class R, class T,
    class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
    class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
    _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
    BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
    typedef _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
    typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
    return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}

template<class R, class T,
    class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
    class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
    _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
    BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
    typedef _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
    typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
    return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}
   
0 请登录后投票
时间:2008-04-06
Trustno1 写道

c/c++又能好到哪里去呢?
你觉得这种代码就不损伤视力?

第1:Trustno1在给出代码的时候最好能指明出处,是官方的,还是某个程序员在恶搞?

第2:给出的代码是否具有普遍性?

第3:我给出的代码(最后那个测试例子除外)都是官方的,
那样的代码风格在整个Erlang/OTP的源代码库中普遍存在,我举的只是代表性的例子。

第4:
Trustno1没有理解我给出的例子的用意,我说“天生”这两字不是随口而出的,
我给你提示几个有关的词(有时间再写个完整的):
Atom、Record、Pattern Matching、function clause、List/Bit String Comprehensions
最重要一点Erlang是一门函数式编程语言。

第5:
我已远离C++

第6:
C++之父已承认C++走入极端

第7:
老实说要在Trustno1发的代码跟我发的代码之间选择,我还是选择看Trustno1发的代码。


后话:
此贴成了精华!!!看来是我打太多字了,JavaEye看我打得辛苦,就。。。

担忧:
呵呵,要是再继续砸Erlang,引来Arm Strong跟我急那就。。。
   
0 请登录后投票
时间:2008-04-06
lichray 写道
握手握手~`

Vim 有下拉屏幕的快捷键,Emacs 应该也有。
FP 在实际应用方面,真的很多。计算机科学方面的那些就不提了,说点“亲切的”。知道 .Net 的垃圾收集器是怎么来的吗?先用 Lisp 写了再转成 C++ 得来的。当然,FP 语言自身的性能也是越来越变态(尤以 Haskell 为甚)。像很多人所热衷的类似服务器、数据库、操作系统等“大型软件”,有很多 FP 写的此类应用。
你说的 Erlang 在语法设计还有一些细节方面的问题,其实我也在暗自偷着乐。这也是我不打算宣传 Erlang 的原因。不过作为世界上极少数支持 PI 演算的语言之一,如果处于并发性能考虑,需要用 Erlang 的话,还是得迁就它。
PS: 要不要考虑加入我们愉快的 Vim 大家庭?:)

哦,对了,Erlang 的编译器实现是非常难读懂的,看过《现代编译原理》的话会知道这一点,但那本书译地又不咋地。而且关于 PI 演算的模拟和优化资料严重欠缺,中文资料==无。我连 Haskell 实现都没勇气一看,还是 Scheme 之类的解释器(或者虚拟机)看着比较顺心。


呵呵,谢过。

我不入派、不结帮。

Vim ? 突然想起好多年前telnet到Solaris用Vi编辑脚本的经历。
   
0 请登录后投票
时间:2008-04-06
引用
第1:Trustno1在给出代码的时候最好能指明出处,是官方的,还是某个程序员在恶搞?

既然你认为这个程序可能是某种恶搞了,那么就是说你认为这个很难读已经严重偏离你所能接受的可读性标准.但是很不幸得告诉你这出自boost,C++的准标准中的bind库.你要是有兴趣可以去这里看源代码.www.boost.org.


引用
第2:给出的代码是否具有普遍性?

可以去尝试阅读boost的function,bind,mpl,preprocess.type_traits,spirit.

引用
第3:我给出的代码(最后那个测试例子除外)都是官方的,
那样的代码风格在整个Erlang/OTP的源代码库中普遍存在,我举的只是代表性的例子。

很不幸得告诉你,boost:bind,function,mpl,type_traits已经是纳入了C++0x标准的的tr1


引用
第6:
C++之父已承认C++走入极端

你的意思是说,这种代码风格已经走极端了?
我怎么看到B教.主是这么说的呢?
引用

The obvious solution for most programmers is to use a library that provides an elegant and efficient platform independent to needed services. Examples are BOOST...

— Bjarne Stroustrup

即便他是这么说过,那你总不能说C++是FP语言是吧?那么按照你上面用恶搞两个词来形容的程度,你是不是应该承认,非FP语言也会很难读?

引用
第4:
Trustno1没有理解我给出的例子的用意,我说“天生”这两字不是随口而出的,
我给你提示几个有关的词(有时间再写个完整的):
Atom、Record、Pattern Matching、function clause、List/Bit String Comprehensions
最重要一点Erlang是一门函数式编程语言。

最重要一点C++是一门imprative语言,而且是一门被广泛应用的imprative语言。


引用
第7:
老实说要在Trustno1发的代码跟我发的代码之间选择,我还是选择看Trustno1发的代码。


但是按照你前面的提问,你显然已经承认这种被广泛应用于C+_+语言的标准库,成为C++语言的编程核心代码已经是在恶搞了,已经远离你所能接受的可读性标准了.
那么放下FP不说,即便是imprative语言里,C++比很多其他种类imprative语言(Pascal?C#?Python?)来说都是一个应用极为广泛的语言。那么是否可以说,你对的代码可读性是否优良的标准与程序语言是否被广泛应用没有任何关系?
如果这个问题的答案是否定的,那么我们是否又可以说,一种语言越是接近于你的语言可读性标准,被广泛使用的可能性越低?或者换一种说法是,你根本没有能力去适应一个真正的被广大程序员所认可的可读性标准?
   
3 请登录后投票
论坛首页 综合技术版 FP

跳转论坛: