2020-12-23

返回主页
snowcicada
代码改变世界
博客园 首页 新随笔 联系 管理 订阅订阅 随笔- 3 文章- 0 评论- 4
Erlang那些事儿第2回之我是模块(module),一文件一模块
  前几篇文章会写得比较基础,但是既然要写一系列的文章,还是得从基础开始写。我刚学Erlang碰到最大的问题是,想网上搜索下语法,结果却是寥寥无几,而且介绍得不是很系统,对我了解一些细节是有影响的,正好我身边有好多Erlang大神,遇到问题可以随时找他们请教,经过自己消化后,分享到这里,希望可以帮助到一些人。这几天偶尔逛一逛博客园,发现这里真是程序员的知识海洋,随便翻两页,就有很多大佬在编写Java并发、Docker镜像、K8S等技术文章,文章的质量我觉得都可以出书了。虽然我之前经常在CSDN,但是没看过这么专业的,看来程序大佬都在博客园。

开始聊正题吧,今天聊到是模块(Module),模块就是存放代码的地方。

C语言有.h头文件和.c源文件,同理,Erlang代码也有这2个玩意儿,只不过后缀有点区别,Erlang的头文件后缀为.hrl,源文件的后缀为.erl。每个Erlang源文件都是一个模块,模块名就是文件名称,每个.erl模块编译后会产生一个.beam文件,就好比.java类编译后会产生一个.class文件。

知识点1:编写一个Hello World模块

创建一个文件hello_world.erl,代码如下:

复制代码
-module(hello_world).

-export([hello/0]).

hello() ->
“Hello Erlang”.

world() ->
“Hello World”.
复制代码
  这个模块非常简单,只有2个函数,分别是hello和world。这里有几个概念,module(模块)、export(函数导出列表)、函数。

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,就一行代码,内容如下:

-define(TEXT, “Hello World”).
  使用define声明了一个宏TEXT,这里的宏跟C语言的宏类似,语法差不多。

修改hello_world.erl,引用下头文件,代码如下:

复制代码
-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 ©ontinue §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的好处有几个,

1、安全性:比如当您重构模块时,您可以知道哪些功能可以安全地重命名,而不需要到外部查找依赖,万一修改了,导致其他模块调用失败也是有可能的;

2、代码气味:编译时不会收到警告;

3、清晰度:更容易看出在模块之外使用哪些功能。

在函数顶部加入一行:-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)的使用,且听下回分解。

作者:snowcicada
  出处:https://www.cnblogs.com/snowcicada
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
分类: Erlang
标签: Erlang
好文要顶 关注我 收藏该文
snowcicada
关注 - 5
粉丝 - 1
+加关注
0 0
« 上一篇: Erlang那些事儿第1回之我是变量,一次赋值永不改变
posted @ 2020-12-23 00:51 snowcicada 阅读(59) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【福利】AWS携手博客园为开发者送免费套餐+50元京东E卡
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· Erlang中module语法
· moduleload
· Erlang保护式
· Erlang编码utf8转urlunicode(二)
· Erlang中的consoperator|
» 更多推荐…

最新 IT 新闻:
· 四周都是“气氛组”,只有你是傻白甜
· 让神经网络给符号AI“打工”,MIT和IBM联合解决深度学习痛点,未来将用于自动驾驶
· 互联网存款产品48小时集体下架 原因定性:“无照驾驶”非法金融活动
· NASA开放新发射台,支持小型运载火箭发射客户
· 花12亿买和解!瑞幸咖啡未来何解?律师:不排除重新上市
» 更多新闻…
snowcicada的头像
昵称: snowcicada
园龄: 3年8个月
粉丝: 1
关注: 5
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 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 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索

找找看

谷歌搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
最新随笔
1.Erlang那些事儿第2回之我是模块(module),一文件一模块
2.Erlang那些事儿第1回之我是变量,一次赋值永不改变
3.Erlang那些事儿之正儿八经的前言
我的标签
Erlang(3)
积分与排名
积分 - 144
排名 - 337615
随笔分类
Erlang(3)
随笔档案
2020年12月(3)
最新评论

  1. Re:Erlang那些事儿第1回之我是变量,一次赋值永不改变
    @Kevin_zheng 谢谢你的支持,坚强2002我知道,他从2011年就开始应用Erlang,并且写了一百多篇博客,已经成为很多程序学习Erlang的学习资料,我也是坚强2002的粉丝,佩服他坚持…
    –snowcicada
  2. Re:Erlang那些事儿第1回之我是变量,一次赋值永不改变
    看了这么久的博客园。第一次早上刷到关于erlang的博客。支持一下。顺便提一句:博客园我就知道 坚强2002 写erlang
    –Kevin_zheng
  3. Re:Erlang那些事儿第1回之我是变量,一次赋值永不改变
    @BigDataForFuture 我目前对Erlang语言的应用是在游戏服务端。它的高并发、无锁、热更新、RPC便捷等特性,恰好符合游戏服务端的需要,可以说很方便省事,对程序员来说可以少造了不少轮子…
    –snowcicada
  4. Re:Erlang那些事儿第1回之我是变量,一次赋值永不改变
    学erlang的运用是?队列?流式计算?
    –BigDataForFuture
    阅读排行榜
  5. Erlang那些事儿第1回之我是变量,一次赋值永不改变(80)
  6. Erlang那些事儿第2回之我是模块(module),一文件一模块(54)
  7. Erlang那些事儿之正儿八经的前言(15)
    评论排行榜
  8. Erlang那些事儿第1回之我是变量,一次赋值永不改变(4)
    Copyright © 2020 snowcicada
    Powered by .NET 5.0.1-servicing.20575.16 on Kubernetes
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值