建立一個文件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)的使用,且聽下回分解。