建立一个文件hello_world.erl,代码以下:github
-module(hello_world).
-export([hello/0]). hello() -> "Hello Erlang". world() -> "Hello World".
这个模块很是简单,只有2个函数,分别是hello和world。这里有几个概念,module(模块)、export(函数导出列表)、函数。shell
export里面只有hello,说明其它模块只能访问到hello函数,没法访问到world函数。hello相似于Java声明为public公有函数,world相似于private私有函数。安全
如今来编译下hello_world模块,并分别执行下2个函数看下返回信息:并发
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace] Eshell V11.1.3 (abort with ^G) 1> ls(). %% ls()函数在终端显示当前目录下的全部文件,输入help().可查看全部命令 hello_world.erl ok 2> c(hello_world). %% c()函数在终端编译hello_world模块,注意不能加.erl后缀 hello_world.erl:18: Warning: function world/0 is unused %% 这里是个警告,提醒world函数没有导出 {ok,hello_world} 3> m(hello_world). %% m()函数在终端显示hello_world模块信息,能够查看该模块的基本信息和导出函数列表 Module: hello_world MD5: f7866776c11b9cfc904dc569bafe7995 Compiled: No compile time info available Object file: /Users/snowcicada/code/erlang-story/story002/hello_world.beam Compiler options: [] Exports: hello/0 module_info/0 module_info/1 ok 4> hello_world:hello(). %% M:F()是Erlang的基本调用方式,M表示模块名,F表示函数名 "Hello Erlang" %% 这里就是hello函数的返回结果 5> hello_world:world(). %% 因为world函数没有导出,没有加入export导出列表,因此调用没导出的函数,会获得一个错误 ** exception error: undefined function hello_world:world/0
知识点2:编写一个有头文件的Hello World模块
建立一个文件hello_world.hrl,就一行代码,内容以下:async
-define(TEXT, "Hello World").
使用define声明了一个宏TEXT,这里的宏跟C语言的宏相似,语法差很少。函数
修改hello_world.erl,引用下头文件,代码以下:post
-module(hello_world).-include("hello_world.hrl"). %% API -export([hello/0, world/0]). hello() -> "Hello Erlang". world() -> ?TEXT. %% 注意这行
Erlang要使用宏,须要在宏的前面加一个问号?,不加编译不过。
从新编译下hello_world模块,执行结果以下:
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace] Eshell V11.1.3 (abort with ^G) 1> ls(). hello_world.beam hello_world.erl hello_world.hrl ok 2> c(hello_world). {ok,hello_world} 3> m(hello_world). Module: hello_world MD5: ceb4d19017c728b4f338ba92ea7bc0cb Compiled: No compile time info available Object file: /Users/guozs/code/erlang-story/story002/hello_world.beam Compiler options: [] Exports: hello/0 module_info/0 module_info/1 world/0 ok 4> hello_world:world(). "Hello World"
知识点3:模块之间能够相互调用,可是不能有循环调用
Erlang的模块能够相互调用,好比在其余语言常常会出现A包含B,B包含A的问题,可是在Erlang这里,只要避免2个模块的函数不互相循环调用,就不会有问题。什么意思呢?假设A模块有一个函数a,B模块有一个函数b,A:a调用了B:b,B:b调用了A:a,那么这样就已经循环调用了,这是不容许出现的。
建立一个文件a.erl,代码以下:
-module(a). %% API -export([a/0]). a() -> b:b().
建立一个文件b.erl,代码以下:
-module(b).%% API -export([b/0]). b() -> a:a().
执行结果:
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace] Eshell V11.1.3 (abort with ^G) 1> c(a). {ok,a} 2> c(b). {ok,b} 3> a:a(). %% 这里卡死了,只能执行Ctrl+C强制退出 BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
程序卡死了,只能强制退出,因此模块虽然能够互相引用对方的函数,可是要注意避免循环调用问题。
知识点4:引入模块函数
建立一个文件calc.erl,代码以下:
-module(calc). %% API -export([add/2]). add(A, B) -> A + B.
修改hello_world.erl,引入calc模块的函数,代码以下:
-module(hello_world). -include("hello_world.hrl"). %% API -export([hello/0, world/0, mod_add/2]). -import(calc, [add/2]). %% 这里引入calc模块 hello() -> "Hello Erlang". world() -> ?TEXT. mod_add(A, B) -> add(A, B).
一行import只能引入一个模块,至于要引入多少函数,能够灵活选择。
执行结果:
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace] Eshell V11.1.3 (abort with ^G) 1> c(calc). {ok,calc} 2> c(hello_world). {ok,hello_world} 3> hello_world:mod %% 按Tab键能够智能提示 mod_add/2 module_info/0 module_info/1 3> hello_world:mod_add(1, 2). 3
知识点5:导出全部函数(export_all)
首先声明,export_all要避免使用,由于会将全部的函数对外导出,会存在一些设计理念的问题。不使用export_all的好处有几个,
一、安全性:好比当您重构模块时,您能够知道哪些功能能够安全地重命名,而不须要到外部查找依赖,万一修改了,致使其余模块调用失败也是有可能的;
二、代码气味:编译时不会收到警告;
三、清晰度:更容易看出在模块以外使用哪些功能。
在函数顶部加入一行:-compile(export_all).,便可导出全部函数,可是编译时会收到一个警告。
修改calc.erl,代码以下:
-module(calc). %% API %%-export([add/2]). -compile(export_all). add(A, B) -> A + B.
执行结果:
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace] Eshell V11.1.3 (abort with ^G) 1> c(calc). calc.erl:14: Warning: export_all flag enabled - all functions will be exported %% 这里会有警告 {ok,calc} 2> c(hello_world). {ok,hello_world} 3> hello_world:mod_add(1,2). 3
模块的内容就先讲到这了,这一回只介绍模块自己,之后会常常编写代码,使用模块就是屡见不鲜了。
本文使用的代码已上传Github:https://github.com/snowcicada/erlang-story/tree/main/story002
下一回将介绍函数(Function)的使用,且听下回分解。