一:开发环境
开始用
Erlang
编程时,多半会把所有的模块和文件放在同一个目录里,然后从这个目录启动
Erlang
。如果这么做,
Erlang
的载入器可以百分百找到你的代码。但是,随着程序变得越来越复
杂,你会想要把它们分成多个易于管理的区块,并把代码放进不同的目录里。另外,当你想要包
含来自其他项目的代码时,这些外部代码会有自己的目录结构。
1.设置载入代码的搜索路径
Erlang
的运行时系统使用一种代码自动载入机制。要让它能正确工作,必须设置一些搜索路
径来找到正确版本的代码。 这种代码自动载入机制实际上是用Erlang
编写的,
代码的载入是“按需进行”的。当系统尝试调用的函数属于一个尚未加载的模块时,就会出现一个异常,系统会尝试寻找缺
失模块的对象代码文件。如果缺失的模块名为
myMissingModule
,代码载入器就会在当前载入路
径的所有目录里搜索一个名为
myMissingModule.beam
的文件。只要找到相符的文件,搜索就会
停止,此文件的目标代码会被载入系统。
可以启动
Erlang shell
然后输入命令
code:get_path()
来找到当前的载入路径值。这里有一个
例子:
1> code:get_path().
[".",
"/usr/local/lib/erlang/lib/kernel-2.15/ebin",
"/usr/local/lib/erlang/lib/stdlib-1.18/ebin",
"/home/joe/installed/proper/ebin",
"/usr/local/lib/erlang/lib/xmerl-1.3/ebin",
"/usr/local/lib/erlang/lib/wx-0.99.1/ebin",
"/usr/local/lib/erlang/lib/webtool-0.8.9.1/ebin",
"/usr/local/lib/erlang/lib/typer-0.9.3/ebin",
"/usr/local/lib/erlang/lib/tv-2.1.4.8/ebin",
"/usr/local/lib/erlang/lib/tools-2.6.6.6/ebin",
...]
以下是两个最常用来操作载入路径的函数:
(1) -spec code:add_patha(Dir) => true {error,bad directory}
%% 向载入路径的开头添加一个新目录Dir
(2) -spec code:add_pathz(Dir) => true {error,bad directory}
%% 向载入路径的末端添加一个新目录Dir
使用哪个通常无关紧要。唯一要留心的是
add_patha
和
add_pathz
是否会导致不同的结果。如果你怀疑载入了错误的模块,可以调用
code:all_loaded()
(返回一个已加载模块的总列表)或
code:clash()
来帮助调查哪里出了错。code模块里的其他一些函数也能够操作路径,不过你很可能用不到这些函数,除非正在做 一些古怪的系统编程。通常的惯例是把这些命令放在主目录(homedirectory
)里一个名为
.erlang
的文件内。 也可以用这样的命令来启动Erlang
:
$ erl -pa Dirl -pa Dir2 ... -pz DirKl -pz Dirk2
-pa Dir
标识会把
Dir
添加到代码搜索路径的开头,
-pz Dir
则会把此目录添加到代码路径的末端。
2.在系统启动时执行一组命令
我们已经知道了该如何在主目录的
.erlang
文件里设置载入路径。事实上,你可以把任意的
Erlang
代码放入这个文件。启动
Erlang
时,它会首先读取并执行此文件里的所有命令。
假设
.erlang
文件内容如下:
io:format("Hi, I'm in your .erlang file-n").
...
启动系统时,我们会看到以下输出:
$ erl
...
Hi,I'm in your .erlang file
Eshell V5.9 (abort with ^G)
1>
如果
Erlang
启动时的当前目录里已经有一个
.erlang
文件,它就会优先于主目录里
的.erlang
。通过这种方式,可以让
Erlang
根据不同的启动位置表现出不同的行为。这对特定的应用程序来说可能很有用。在这种情况下,多半应该把一些打印语句添加到启动文件里,否则你可能会忘记本地启动文件的存在,从而感到非常困惑。
注:在某些系统里,主目录的位置并不清晰,或者可能和你认为的不一样。要找出Erlang认定
的主目录位置,可以这么做:
1> init:get_argument(home).
{ok,[["/home/joe"]]}
通过上面的信息可以推断Erlang认为你的主目录是/home/joe。
二:运行程序的不同方式
Erlang
程序被保存在模块里。编写完程序之后,必须编译它才能运行。也可以通过无需编译的escript
来直接运行程序。接下来将展示如何用多种方式编译和运行两个程序。这两个程序略有不同,启动和停止它们的方式也有区别。第一个程序hello.erl
只打印“
Hello world
”。它不负责启动和停止系统,也不需要访问命令行参数。与之相对,第二个程序fac
需要访问命令行参数。下面是基本的程序。它打印出的字符串是“Hello world
”再加一个换行符(
~n
在
Erlang
的
io和io_lib
模块里被解释为换行符):
%% hello.erl
-module(hello).
-export([start/0]).
start()->
io:format ("Hello world-n").
上述代码可以用三种方式编译运行它:
1.在 Erlang shell 里编译和运行
我们从启动
Erlang shell
开始:
$ erl
...
Eshell V5.9 (abort with ^G)
1> c(hello).
{ok,hello}
2> hello:start().
Hello world
ok
补充说明<快速脚本编程>:
我们经常希望能在操作系统的命令行里执行任意的 Erlang 函数。 -eval 参数非常适合进行快速脚本编程。这里有一个例子:erl -eval 'io:format("Memory: ~p~n", [erlang:memory(total)]).'\ -noshell -s init stop
2.在命令提示符界面里编译和运行
可以直接在命令提示符界面里编译程序。如果只是想编译一些代码而不运行它们,这就是最
简单的方式。它的做法如下:
$ erlc hello.erl
$ erl -noshell -s hello start -s init stop
Hello world
$
注:所有的shell命令都假定用户已经在他们的系统里安装了合适的shell,并且erl和erlc 等命令能直接在shell里执行。
第
1
行的
erlc hello.erl
编译了
hello.erl
文件,生成了一个名为
hello.beam
的目标代码文件。第二个命令有三个选项:
(1)-noshell 以不带交互式 shell 的方式启动 Erlang (因此不会看到 Erlang 的“徽标”,也就是通常系统启动时首先显示的那些信息)。(2)-s hello start 运行 hello:start() 函数。 注意 :使用 -s Mod ... 选项时, Mod 必须是已编译的。(3)-s init stop 在之前的命令完成后执行 init:stop() 函数,从而停止系统。erl -noshell ...命令可以放在 shell 脚本里,所以通常会制作一个 shell 脚本来运行程序,里面会设置路径(用-pa Directory )并启动程序。
在这个例子里用了两个
-s ..
命令。命令行里的函数数量是不受限制的。每个
-s ...
命令都
由一个
apply
语句执行,运行完毕后再执行下一个命令。
下面是一个启动hello.erl的例子:
%% hello.sh
#!/bin/sh
erl -noshell -pa /home/joe/2012/Book/code\
-s hello start -s init stop
注:这个脚本需要一个指向hello.beam文件所在目录的绝对路径。所以虽然这个脚本能在我的机器上工作,但是你必须修改一下才能让它在你的机器上运行。
为了运行
shell
脚本,我们需要
chmod
这个文件(只需一次),然后就可以运行它了。如下所示:
$ chmod u+x hello.sh
$ ./hello.sh
Hello world
3.作为Escript运行
可以用
escript
来让程序直接作为脚本运行,无需事先编译它们。为了让
hello
作为
escript
运行,
我们创建了下面的文件:
%% hello
#!/usr/bin/env escript
main(Args)->
io:format ("Hello world ~n").
这个文件必须包含一个
main(Args)
函数。当它从操作系统的
shell
里调用时,
Args
会包含一
列用原子表示的命令行参数。在
Unix
系统上,无需编译就可以立即运行,就像下面这样:
$ chmod u+x hello
$ ./hello.sh
Hello world
注:这个文件的文件模式必须设置为“可执行”(Unix系统上可以输入命令chmod u+x File),这个操作只须做一次,不是每次运行程序时都要做。
4.带命令行参数的程序
“
Hello world
”没有任何参数。让我们用一个计算阶乘的程序来重复这个练习。它接受单个参数。首先是它的代码:
%% fac.erl
-module(fac).
-export([fac/1]).
fac(0) -> 1;
fac(N) -> N*fac(N-1).
可以像这样编译fac.erl并在Erlang shell里运行它:
$ erl
...
1> c(fac).
[ok,fac}
2> fac:fac(25).
15511210043330985984000000
如果希望在命令行里运行这个程序,就需要修改它,让它能够接受命令行参数。
%% fac1.erl
-module(fac1).
-export([main/1]).
main([A])->
I = list_to_integer(atom_to_list(A)),
F = fac(I),
io:format("factorial ~w = ~w~n",[I, F]),
init:stop().
fac(0) -> 1;
fac(N) -> N*fac(N-1).
然后可以编译并运行它:
$ erlc facl.erl
$ erl -noshell -s facl main 25
factorial 25 = 15511210043330985984000000
注:这个函数的名称main没有什么特殊含义,你可以给它取任何名字。重点是函数名和命令行里的名称要一致。
最后,可以把它作为
escript
运行:
%% factorial
#!/usr/bin/env escript
main([A]) ->
I = list_to_integer(A),
F = fac(I),
io:format("factorial ~w = ~w~n",[I, F]).
fa(0)->1;
fac(N)->
N * fac(N-1).
无需编译就可以运行它,如下所示:
$ ./factorial 25
factorial 25 = 15511210043330985984000000
当然,到这剩下的就是使用开发工具来导入相关编译器,从而更好的节省我们每次改完代码用命令去编译和测试 。
三:在IntelliJ IDEA 中进行Erlang的编译和使用
可先进入官方下载最新版的erlang otp,网址如下:Downloads - Erlang/OTP
也可以使用百度网盘去直接获取,我已分享,不过是用于win的erlang 24.3,网盘链接:https://pan.baidu.com/s/1nYKtH4XtKeT0FS1_inji7w?pwd=erlc
提取码:erlc
1.解压文件,并复制文件到你想放入的目录,如下:
进行浅安装:
2.win配置环境变量,路径为:D:\erlang 24.3\erlang 24.3\erl-24.3.4.12\bin
配置变量:
当cmd里执行erl时出现:
就表示配置成功!!
3.IntelliJ IDEA中进行安装,先下载erlang插件:
然后再在File ->Setting中的SDKs里面更换erlang的SDK就行