Erlang-China

erlang 中文社区

CouchDB 的作者 Damien Katz 炮轰 Erlang 的语法


CouchDB 的作者,即知名的 Damien Katz ,虽说他用 Erlang 写出了名动江湖的 CouchDB ,但对于“他喜爱的 Erlang ”,还是发了 一满车的牢骚 来表达他对 Erlang 诡异语法的抱怨。

这一车牢骚主要集中于:

Basic Syntax
If Expressions
You Say String of Characters, I Say List of Integers
Functional Programming Mismatch
Records
Give me memory, or give me death!
Code Organization
Uneven Libraries and Documentation

具体来说,就是:

Basic Syntax,主要是抱怨在不同的上下文中 ; 和 . 都作为代码的分割符号来使用,这使得拷贝粘贴代码需要额外的小心处理这些符号。不过我倒没觉得别扭 ; 表示的是一个子句的结束,若要拷贝一个完整的函数(或者 case 的子句),确实是应该包括它的多个子句的。

If Expressions,主要在于 if 不能使用自定义的 函数 作为判断条件,而且还必须(包括 case)要有一个返回值。这一点在 erlang 文档中已经明确指出了原因 if 只能用无副作用的 bif 来作为判断条件。而 case 和 if 作为一个语句,都必须保证要有返回值(在 erlang 中所有的语句都要有值,比如说 undefined 这个 atom)。

You Say String of Characters, I Say List of Integers,主要是没有内置的 String 类型,而是作为 List 来对待引起的。Yariv 也倾向于赞同这一点,他提出的”将 regx 之类的函数扩展到 binary,以 binary 来处理 string”我谨慎赞同(如果能够妥善解决 utf8 的话)。

Functional Programming Mismatch,主要是抱怨“不可变的变量”带来的不适。看过 Joe thesis 的人能够理解为什么 Erlang 要搞“不可变的变量”,我觉得正是因为 Erlang 在这个问题上的决策才带来了它的优越性。用 Erlang 就必须要忍受它的“不可变的变量”,我觉得这是一个风格问题。

Records,怪异的 Record 语法。这个我赞同,改成任何一种简略一些的语法应该是可以的。

Give me memory, or give me death!,Erlang 在内存分配失败时的 exit(1) 处理让 Damien 相当不适应,但,这就是 Erlang 与众不同的异常处理策略。换句话说,也是它能量的一部分。照理说 VM 应该重启(如果配置了 Monitor),但 Damien 提到的 VM 没有成功重启,Klacke 在回帖中表示,这或许是一个 bug 。

Code Organization,只有 module 这一种代码组织方式让他不爽。无语,我只能说,这事风格冲突。

Uneven Libraries and Documentation,缺少库和文档,老问题了。确实该改进。

总结一下,对于 Damien 的抱怨,我赞同他对于 String, Records, Libraries and Documents 的看法。其余的,我认为大多出于设计决定,也是可以习惯的。如果理解了“不可变的变量”,“减少副作用”以及“速错”,这些异乎寻常的设计决定是如何做出的,那么看到这样诡异的代码,也许会更加容易认同。

另外,此前我和 dcaoyuan 也聊起过对 Erlang 语法和库的不适应。对于语法,我现在认为那是一个习惯问题,的确是与你之前所习惯的大不相同,但你总能适应。而对于库,我比较赞同他的话:“Erlang 过去太专注于自己狭窄的应用领域,用在其他的领域,你会发现它缺乏一些显而易见的支持库。但你选择了 Erlang 就要做好思想准备,要么等待 OpenSource 社区的贡献,要么就自己动手丰衣足食。”

再有,生命不就在于折腾么,折腾到 Erlang 必然有自己的理由,这些也许正是乐趣的一部分——这里拿 Yariv 的话作为结尾——“Like any language, Erlang has some warts. But if it were perfect, it would be boring, wouldn’t it? :)”





Comments



1
Author:  simohayha | Date:  March 10, 2008 | Time:  7:54 pm
2
Author:  zj | Date:  March 11, 2008 | Time:  11:00 am

让我想起了使用vim
要么选择,要么返回…………..

3
Author:  Trustno1 | Date:  March 12, 2008 | Time:  11:53 am

对于被C语法族语言惯坏的程序员来说,遇上Erlang已经是非常幸福的事情了.如果高并发高可靠的名头被戴在Haskell,OCaml上面,我看他们除了跳楼之外恐怕没啥其他出路了.

4
Author:  Trustno1 | Date:  March 12, 2008 | Time:  11:58 am

另外,record语法实则和immutable问题是捆在一块的.比如dcaoyuan 的record bird.
你最多拿.语法来做getter,遇到setter照样没辙.我曾经想过一个setter的语法.
NewRecord=Record.field

5
Author:  Trustno1 | Date:  March 12, 2008 | Time:  12:07 pm

我曾经想过一个setter的语法.NewRecord=Record.field

6
Author:  Trustno1 | Date:  March 12, 2008 | Time:  12:08 pm

靠这个回复有问题啊.半角的<-显示不出来.

7
Author:  jackyz | Date:  March 12, 2008 | Time:  6:41 pm

半角的“ < ”是html标签的一部分嘛。用个[code][/code](把[]变成尖括号)框起来好了。

Record 语法刚开始确实觉得巨烦巨冗长,它的 get 用起来怒啰嗦(感觉编译器应该给我自动判断某个变量是不是某record就好了嘛,免得多敲键盘)很不爽。但用来做 set 就确实很爽(没变化的字段就不用啰里啰嗦的再写了,用getter和setter的恐怕就必须要搞个通用方法来做这件事),再加上匹配语法啥的,用着用着,也感觉没那么恶心了。

...
-
record(person, {name=undefined, age=0, address=undefined}).
...
R1 = #person{age=28},
Age1 = R1#person.age,
R2 = R1#record{age=29, address="some address"},
#
record{age=29, address=Address} = R2
...

俺在开始的几个月也抱怨了一阵子,后来也就慢慢适应了。

8
Author:  trustno1 | Date:  March 14, 2008 | Time:  4:36 am

Record 语法刚开始确实觉得巨烦巨冗长,它的 get 用起来怒啰嗦(感觉编译器应该给我自动判断某个变量是不是某record就好了嘛,免得多敲键盘)很不爽

那是因为Erlang完全没类型的阿,Haskell就抹油这样的问题.#person实际上就是人肉标注类型.

9
Author:  trustno1 | Date:  March 14, 2008 | Time:  4:38 am

更正一下也不能说是没类型,说的准确一些应该是Erlang的类型是by layout而不是by name的,by layout的好处就是pattern match方便,当然也要付出代价就是相同的layout不同的类型要区分出来就要靠人肉标注了.

10
Author:  xrfang | Date:  March 19, 2008 | Time:  5:03 pm

这位大师的评论我只同意一点,就是erlang的record实在可以用笨拙形容。其他我觉得都很好。比如,;.作为语句结尾符的用法,我觉得意思很明确。

我自己发现了erlang的一些奇怪的地方,奇怪这个用词不妥,应该说是对初学者的陷阱。最明显的一个就是变量首字母必须大写。这个倒也罢了,问题是,不大写,不报错!!!大家看看下面这段代码:

[t * t || t

11
Author:  xrfang | Date:  March 19, 2008 | Time:  5:05 pm

晕菜,楼上我写的代码是:

[ t * t || t <- lists:seq(1, 10)]

12
Author:  jackyz | Date:  March 19, 2008 | Time:  7:13 pm

变量首字母大写恐怕还是必须的吧,要不然,如何区分 atom 和变量呢?

[ t * t || t <- lists:seq(1, 10)]

这一句,是合法的语句,执行结果是 [] 。其含义你可以用下面这一句来理解

[ t * t || t <- [t, u, v]]

执行时会告诉你 t * t 不是合法的操作符。这是因为 t <- [t, u, v]的结果为 [ t ] 对 atom 的 t 执行 t * t 是非法的操作。这一点可以这样印证。

[ t || t <- [t, u, v]]

其执行结果就是 [t] 。

目前的 erlang-china.org 是以 blog 形式存在的“资料收集/消息发布”处。 bbs/maillist 的感觉可以在 erlang-china@googlegroups.com 论坛找到。



Write a Comment

Note: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>