为什么不是「如日中天」的 Elixir 呢? 我也想问, 也不知道. 就只是想先入坑 Erlang呢.

因为「主流」的语法先入为主, 导致 Erlang 学起来比 Ruby, Java, Swift 感觉要难了不少. 倒不是说不好, 纯粹只是习惯问题. 在舒适区呆久了, 会形成思维惰性, 也会加深排他性.

Learn You Some Erlang for great good!Programming Erlang 交替看了一星期. 还只是在顺序编程这一块的语法上.

一些意料之外但又在情理之中的语法.

Erlang 的变量首字母是大写的, 虽然叫「变量」, 但一旦赋值就不能更改.

1
2
3
4
5
% erl
1> X = 1.
1
2> X = 2.
** exception error: no match of right hand side value 2

其实, Erlang 的这等号不叫赋值, 叫绑定会正确一些. 绑定了就不能变. 刚开始也许接受困难. 但是, 好处是看代码会简单明了一些. 不然改来改去还得一步步去回溯.

表达式序列必须要以点号(.)结尾 而不是常见的 ; 也不是像 Ruby 那样不用写

可以用逗号来分隔表达式, 但是只会显示最后一个表达式的执行结果(其他表达式也都执行了). 也许看起来很奇怪, 但是, 其实咱们英文中文不都是用句号作为结尾的么?

布尔操作符 and 和 or 对操作符两边的参数都会去求值. 如果想要的是一个短路操作符(只在有必要时, 才去求值右边的参数), 可以使用 andalso 和 orelse.

原子 atom, 像 Ruby 中的 Symbol, 但省去冒号了.

pry

1
2
3
4
5
[1] pry(main)> ruby
NameError: undefined local variable or method `ruby' for main:Object
from (pry):1:in `__pry__'
[2] pry(main)> :ruby
=> :ruby

erl

1
2
3
Eshell V9.0  (abort with ^G)
1> ruby.
ruby

但有一个真正是奇葩的语法, 小于等于的写法居然是 =<,

最后, 列表与字符串的那点小事.

1
2
3
4
5
6
7
8
9
[]
[1, 2, 3, 9, 100]
[zero, two, four]
[{google, "Android"}, {apple, "iOS"}]

% 上面这些都是一些列表, 注释用百分号

% 管道符号 | 左侧的元素 1 与右侧的空列表, 合并构成一个新的列表, 结果是 [1]
[1 | []].

同理, 这里结果是[1, 10, 100]

1
[1 | [10, 100]].

新元素是从左侧往右侧添加的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
% erl
1> [1|[]].
[1]
2> [[]|1].
[[]|1]

[5, 4, 3 | [2, 1]].
% 这样会得到 [5, 4, 3, 2, 1], 但理解这一句应该是依次添加元素 3, 4, 5 到列表 [2, 1]的前头

[a, b, c, d] ++ [x, y, z].
% 使用 ++ 给任意列表追加元素, ++ 左侧的列表长度决定了运算的耗时, 与右侧列表长度无关

新内容(通常较短)应该尽量从左侧加入列表, 即便最终得到的是逆序也无妨. 随着新元素的加入, 列表越来越长, 与其每次都为了在列表末尾添加元素而反复遍历列表, 还不如最后用一个函数调用快速反转逆序的列表. 《Erlang OTP并发编程实战》

其实列表也还好理解, 但是问题来了. Erlang 居然没有字符串. 虽然, 可以用双引号输入一串字符, 比如

1
2
3
4
1> "Hello".
"Hello"
2> "abcd".
"abcd"

然而, 其实质还是列表, 由该字符串各个字符的数字编码所对应的整数所组成的一个列表. 上面俩等价于

1
2
3
[97, 98, 99].

[72, 101, 108, 108, 111].

在 Erlang shell 中为了区别对待字符串和普通列表, 会检查列表的元素, 是否全部为可打印字符. 如果是, 就打印成双引号字符串, 否则打印出一个整数列表.

简单过了一遍 Erlang, 下回具体一些吧, 给自己立个 Flag, 完成自己的 Erlang 周记.