Erlang Thursday – user_default

今天的Erlang Thursday我们来看看user_default模块。

我是在想验证当我在erl shell中调用 c/1 和 l/1 的函数的版本的时候偶然发现这个模块的,然后研究 shell_default 的文档。

文档中提到,如果我们想让一些函数在shell里直接可用,我们可以生成一个名字为user_default的模块,然后在自己的 .erlang 文件里指定该模块的路径,这样的话user_default模块里的导出函数就可以直接在shell里可用了。

既然我手上有一个 fizzbuzz 的例子,那么让我们开始按文档的说明生成一个user_default模块证明我们可以让它正常工作。我们将把它放在我们home目录的tmp目录里。

~/tmp/user_default.erl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-module(user_default).
-export([fizzbuzz/1]).
fizzbuzz(N) ->
Translations = lists:map(fun translate/1, lists:seq(1, N)),
lists:foreach(fun(Item) -> io:format("~s~n", [Item]) end, Translations).
translate(N) when N rem 3 =:= 0 andalso N rem 5 =:= 0 ->
'FizzBuzz';
translate(N) when N rem 3 =:= 0 ->
'Fizz';
translate(N) when N rem 5 =:= 0 ->
'Buzz';
translate(N) ->
integer_to_list(N).

在我们的home目录下新建一个 .erlang 文件,添加如下内容,指明我们刚刚创建的user_default文件的路径。

~/.erlang

1
code:load_abs("tmp/user_default").

如果你已经有一个 .erlang 文件,那么在这个文件的第一行必须是 code:load_abs/1 函数,其参数为 user_default 模块。

确定上述两个文件都保存好了,然后打开erlang shell来尝试调用 fizzbuzz/1 。

1
2
3
4
5
6
7
8
$ erl
Erlang/OTP 17 [erts-6.2.1] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V6.2.1 (abort with ^G)
1> fizzbuzz(20).
** exception error: undefined shell command fizzbuzz/1
2> q().
ok

然而并没有像文档里讲的那样起作用。我意识到,我们用的是 load_abs 函数,并且 user_default 是一个新模块,这个错误可能是因为没有文件可装载。让我们用erlc编译这个模块,然后再尝试。

1
2
3
4
5
$ cd tmp/
$ erlc user_default.erl
$ ls user_default.*
user_default.beam user_default.erl
$ cd ..

我们现在有一个BEAM文件在~/tmp目录里,所以让我们再次启动Erlang shell并尝试调用 fizzbuzz/1 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ erl
Erlang/OTP 17 [erts-6.2.1] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V6.2.1 (abort with ^G)
1> fizzbuzz(20).
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
ok
2>

终于正常工作了!我们现在可以在shell里不需要指定模块名而直接调用 fizzbuzz/1 。

更多的关于 .erlang 文件的信息可以阅读 Erlang中关于配置部分的文档

原文链接: https://www.proctor-it.com/erlang-thursday-user_default/