欢迎入坑Erlang,关键字:
函数式,高并发,容错,热更新,分布式
安装
erlang的安装非常简单,直接去官网下载编译好的二进制安装包即可。需要注意的是文件名格式是OTP_平台_版本.后缀
,其实就是erlang的安装包,只是不叫erlang这个名字,OTP是开放电信平台的意思,是erlang官方的开发框架,也是erlang分发套件的一部分,希望不要产生误解。
erlang没有专用的IDE,但是提供了常用代码编辑器的插件:
- Vscode
- Emacs
- Vim
- Intellij IDEA
- Sublime Text
- Atom
- Eclipse
具体细节可以参考官方社区的Editor/IDE
栏。
认识shell
安装完成后打开Erlang图标就能打开erlang的shell,在这里可以执行erlang表达式,或者编译erlang源文件。
前面打印了erlang的一些信息和提示,后面的1>
就是erlnag的命令提示符,没错就是数字1,erlang是用行号>
作为命令提示符的。
如果你好奇心比较重,不小心按下了ctrl+G
,就会进入一个需要输入命令的地方,提示符变成了-->
。不要慌,输入h
或?
回车,就能看到可用的命令列表了,按q
可以退出erlang shell,再重新打开就行了。
除了双击elang图标,也可以在cmd/shell中输入erl
回车来进入erlang shell。要回到cmd可以按ctrl+c
或者输入q().
或者erlang:halt().
回车,区别是后者会立即退出erlang shell。注意最后的.
号是必须的,erlang的语句是以.空白
结尾的,空白
可以是空格,回车,制表符等。这和我们写英文句子的逻辑是一致的。
erlang shell提供了一些快捷键来帮助我们编辑命令和表达式,熟练之后可以提高使用shell的效率。
快捷键 | 功能 | 速记 |
---|---|---|
ctrl+A | 光标移至行首 | Ahead |
ctrl+E | 光标移至行尾 | End |
ctrl+D | 删除当前字符 | Delete |
ctrl+F或右箭头 | 向前移动一个字符 | Front |
ctrl+B或左箭头 | 向后移动一个字符 | Back |
ctrl+p或上箭头 | 上一条命令 | Pre |
ctrl+N或下箭头 | 下一条命令 | Next |
ctrl+T | 交换最近的两个字符 | Transfer |
Tab | 自动补全 | 国际惯例 |
注意,以上这些快捷键只在erlang自带的shell中有效,在通过cmd/shell打开的erlang shell中是没法使用的。
运行代码
erlang表达式可以直接在shell里运行,比如我们可以先写一些简单的算术表达式。
1> 1+2.
3
2> 3*4.
12
erlang源代码放在.erl
文件中,erlang源代码的运行方式同java一样,需要先编译成目标代码.beam
文件,然后在erlang虚拟机BEAM中运行。与java不同的是,JVM是堆栈虚拟机,而BEAM是寄存器虚拟机,后者执行速度更快。
首先我们新建一个first.erl
文件,然后输入下面的代码,后面我们会介绍erlang的语法,现在照着写就行。
-module(first).
-export([start/0]).
start() ->
io:format("hello erlang").
在erlang shell中运行:
- 在
first.erl
文件所在目录打开cmd,输入erl
进入erlang shell。 - 输入
c(first).
编译first.erl
,如果成功会看到{ok,first}
的输出。这一步会生成一个first.beam
的文件。 - 输入
first:start().
运行first
模块的start
函数,不出意外的话,你会看到屏幕上输出的hello erlangok
,ok
是erlang shell输出的内容,表示执行成功,在cmd上没有换行显示而已。你可以在源代码中"hello erlang"
后加上换行符,这样ok
就换行显示了,如"hello erlang\n"
或者"hello erlang~n"
,\n
和~n
都表示换行。
不进入erlang shell执行:
- 打开命令行输入
erlc first.erl
编译first.erl
。如果成功会生成first.beam
文件。 - 输入
erl -noshell -s first start -s init stop
,不出意外你应该能看到hello erlang
的输出。-noshell
以不带交互的方式启动erlang shell,-s Mod Fun
表示执行Mod
模块下的Fun
函数。这里我们执行了两个函数,第一个是我们编写的start
函数,第二个是init
模块下的stop
函数,我们用它来退出erlang shell,所以当hello erlang
打印完以后,我们又回到了系统命令行。如果不带-s init stop
,就无法退出erlang shell了,也无法再执行别的命令,因为我们是以非交互式方式启动erlang sehll的。最后要注意的是-s
选项不会去编译源代码,所以必须先编译。
使用-eval
选项运行:
- 在命令行输入
erl -eval 'io:format("hello_erlang").' -noshell -s init stop
。用这种方式可以在系统命令行中快速运行erlang函数,注意在powershell中千万不要把"hello_erlang"
写成"hello erlang"
,因为它会在空格处截断命令,大坑一个。当然我们也可以用它来运行first:start()
函数,前提是已经编译过。
使用escript
运行:
-
新建一个
hello.erl
文件,输入以下代码。-module(hello). main(Args) -> io:format("hello erlang~n").
-
在
hello.erl
所在目录打开命令行,输入escript hello.erl
,不出意外应该能看到输出hello erlang
。这里需要注意main
函数是必须的,它是脚本的入口。使用escript
不需要编译源代码,而是像脚本一样运行。
在erlnag shell中运行代码这种方式中,我们是通过cmd进入erlang shell的,如果直接打开erlang shell或者在别的目录下启动的erlang shell,会得到一条错误信息,说找不到start
函数。此时可以通过c:cd("路径")
切换到代码所在目录,例如我们直接打开erlang shell执行之前的代码:
1> first:start().
** exception error: undefined function first:start/0
2> c:cd("E://code//erlang//learn").
e:/code/erlang/learn
ok
3> first:start().
hello erlang
ok
既然有cd
,一个合理的猜测是有没有c:ls()
,你可以自己验证下,举一反三。
寻找代码
erlang是如何寻找源代码的呢?在前面的例子中,我们都是在源代码所在的目录启动erlang shell,可以肯定的是erlang shell能够从当前目录寻找代码,我们可以使用code:get_path().
来查看全部的代码搜索路径。
1> code:get_path().
[".","d:/program/Erlang OTP/lib/kernel-8.5.3/ebin",
"d:/program/Erlang OTP/lib/stdlib-4.2/ebin",
"d:/program/Erlang OTP/lib/xmerl-1.3.30/ebin",
"d:/program/Erlang OTP/lib/wx-2.2.1/ebin",
"d:/program/Erlang OTP/lib/tools-3.5.3/ebin",
... ...
这是一个很长的列表,可以看到第一个就是当前路径.
,erlang shell会递归搜索这些路径来查找代码。
为了避免每次都用cd
去切换目录,我们有两种方式可以将代码目录添加到erlang的代码搜索目录列表。
第一种方式是在命令行启动erlang shell 时通过-pa
和-pz
来启动erlang shell。
a
是第一个字母,z
是最后一个字母,所以用pa
来表示添加到头部,pz
表示添加到尾部。
erl -pa path1 -pa path2 -pz path3 -pz path4
或者
erl -pa path1 path2 -pz path3 path4
-pa
和-pz
一次可以添加多个路径,也可以多次使用-pa
和-pz
来添加。使用这种方式添加路径有以下特点:
- 只在当前会话有效。
- 添加是临时的。
第二种方式是在用户主目录的.erlang
文件中添加。如果没有,可以手动创建一个,如果不知道自己的用户主目录在哪儿,可以使用init:get_argument(home).
查看。
code:add_patha("E://code//erlang").
启动erlang,再次输入code:get_path().
回车,可以看到开头多了一个E:/code/erlang
。如果要在末尾添加,就使用code:add_pathz
函数,我相信你已经猜到了。
erlang shell每次启动前都会去执行.erlang
文件中命令,这样就可以避免我们每次启动erlang shell都去添加一遍目录。实际上我们可以在这里写任意代码,比如加个欢迎词。
io:format("欢迎进入Erlang的世界~n").
code:add_patha("E://code//erlang").
同样,code:add_patha
和code:add_pathz
也可以在erlang shell中执行,并没有什么神奇的。
一些约定
介绍完如何运行erlang代码后,相信你已经迫不及待想要写些代码来试试了,不过在正式进入语法篇之前,我们先介绍一下erlang语言中的一些约定。
- erlang语句以英文句号
.
加上一个空白符结尾,空白符包括空格,制表符和换行。这一点在之前的例子中我们已经见过了。;
在erlang中用于子句的结尾,这些都与文章的书写习惯是一致的,应该是很容易被接受的。 - erlang的变量名必须大写字母开头,因为小写字母开头的会被识别为原子。作为初学者这的确让人惊讶,关于原子以及这样做的原因我们后边再细说。erlang是函数式编程语言,严格来说不能叫变量,因为它们其实不可变。
- erlang中
%
开头的是注释,并且它没有块注释。某些IDE会识别%%
并做一些格式化,注意这不是编译器的功能,对erlang来说,%%
和%
没区别。 - erlang在书写函数名时要带上参数个数,比如前面例子中的第二行代码
-export([start/0]).
这行代码的含义是导出start/0
函数,后面的/0
表示函数start
有0个参数。 - erlang的函数和变量都是私有的,只有通过
-export
导出的才能在模块外访问。 - 模块名和文件名必须相同。模块名通过
-module
指定,必须和不带后缀的文件名相同。
下一篇:语法篇