----------------小技巧-----------------------------

因为这一课开始,我们要使用Erlang文件操作,所以,我们期待启动shell的时候,当前目录最好是是我们的工作目录,比如,打开erl shell环境,默认目录就是“C:/Users/Kenneth/Documents/Erlang”。我们需要编辑C:/Program Files/erl5.9.1/usr(启动shell后,执行pwd().来查看当前目录是是什么)下的.erlang文件来达到这一目的。windows下创建.erlang是件头大的事,图形界面操作时,系统提示“必须要输入文件名”,可以先创建一个文本文档,然后在cmd环境下执行move xxx .erlang来改文件名。

.erlang文件内容如下:

io:format("according to the file .erlang in ~p~n",
[element(2, file:get_cwd())]).
%% Edit to the directory where you store your code
io:format("cd ").
c:cd("C:/Users/Kenneth/Documents/Erlang").
io:format("...~n").
io:format("OK! Now in:~p~n", [element(2, file:get_cwd())]).

这样下次启动shell,它会自动切换当前目录为我们的工作目录。

---------------------------------------------------

Erlang里面会把某一类的function放到一个单独的文件中,然后这个整体被叫做Module;Erlang中所有的函数都必须放到Module里面。所以,除了前面两课讲到的基本数据类型,Module也是Erlang的基本元素之一。

1、调用函数时,我们必须以这样的结构:Module:Function(Arguments)。除了BIFs。

2、BIF(Build In Function)使用时不需要指定module,这是因为虚拟机启动时,默认加载了Erlang这一module里的所有函数进来。所有的arithmetic,logic,和boolean operator这些,也都是在Erlang 这一module中。例如:

> erlang:element(2,{a,b,c}).
b
> element(2,{a,b,c}).
b
> lists:seq(1,4).
[1,2,3,4]
> seq(1,4).
** exception error: undefined shell command seq/2

上面的代码中,不管我们指不指明element函数属于Erlang模块,它都是可以被执行的;另外一面,seq属于lists模块,所以,如果不指定它属于哪个module,系统就会抛出错误。

ps:不是所有Erlang中所有的函数都被加载,有一些不常用的,是没有加载的。

3、除了需要一个单独的文件,并且给他起一个别致的名字以外,Functions和Attributes这两样也是一个Module不可缺少的。Function不必多讲,没有Function,建立Module做什么?OK,那Attributes又是做什么用的?Attributes里面存放了描述Module自身用的一些metadata,比如它自己的名字,哪些函数是外部可以调用的,代码作者啊等等这些。编译器会将这些信息放到编译完的代码中去。这样,即使是拿到编译过的代码,我们也可以查看这个module的基本信息,而不用再去翻source code。

attributes的定义方法是 -Name(Attribute)。

4、第一个Attributes必须是“-module(Name)”;这里的Name还必须和存放Module的file同名。这里的name便是我们按照MF(A)这样调用函数时,必须要用到的module name。

5、然后另一个必不可少的Attributes是" -export([Function1/Arity, Function2/Arity,...,Function3/Arity])"。其中,Function是函数名称,Arity是这个函数接受几个参数。在Erlang中,相同名称不同参数个数的函数是当做不同函数对待的,这类似OOP里面的重载。

6、还有一个attributes比较重要“-import(Module, [Function/Arity, ..., Function/Arity])”,其作用就是将module中的函数加载进来,然后,我们调用的时候就直接F(A)即可(就像虚拟机一开始对Erlang这一module做的一样)。这里有个问题,很多人都不大赞成用import来完成工作。主要因为,本来在设计module的时候,只需要考虑function name在本module内唯一就好了,但是,现在如果从不同的module引入function,使用的时候,就得小心翼翼了。

7、define是另一个比较重要的attributes,使用方法是“-define(MACRO, some_value)”。这个和C中的define有点像。同样的define也是常被用来定义一些常量和短的函数。Erlang的宏定义使用的时候,格式为“?MACRO”。

ps:?MODULE会被换成module name,as a atom;?FILE会被换成本文件的filename,as a string;?LINE会被换做所在行的行号。

ps:同样的我们可以使用-ifdef(MACRO),-else和-endif等宏定义检查语句,比如:

-ifdef(DEBUGMODE).
-define(DEBUG(S), io:format("dbg: "++S)).
-else.
-define(DEBUG(S), ok).
-endif.

如此,我们可以在后面的代码中使用?DEBUG("entering xxx function!~n")这样的语句来添加调试信息。这样,如果我们如果在编译的时候使用了DEBUGMODE开关,那么,调试信息将被打印出来;如果我们没有使用DEBUGMODE开关,这句只是被替换为ok这一atom,单独这样一条语句的话,是什么也不会做。

8、函数的定义语法是Name(Args) -> Body(结束符)。Name必须是一个atom。Body可以是一条或者多条由逗号隔开的Erlang语句。(结束符)则是分号或者句号之一,我们在定义多个同名的函数时,每个函数之间使用“;”号隔开的,而所有函数定义实现都已经完成了之后,我们要在最后加一个“.”。

9、另外还有一个比较常见的attributes是:

-spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType."

这里,如果是同一module内,我们可以把“Module”字段略去不写。

这一语句是用来定义函数规范的,如果我们定义了函数规范,那么我们就可以在运行前使用dialyzer来对程序进行静态检查,这样就可以发现一些我们由于手抖造成的错误。

下面这句,意思是,我们定义了一个函数index(),它需要三个参数,第一个参数可以是任意的数据类型,第二个是正整数,第三个参数是一个list(这里的[any()]和lists()是等价的),而return的是一个非负数。

-spec( index(any(), pos_integer(), [any()]) -> non_neg_integer() ).

另外与spec相关的还有type,具体可以戳下面:

http://erlangdisplay.iteye.com/blog/404570

================分割线===========================

so,一个module就这样建好了,一起来看看我们建的第一个module:

-module(helloworld).
-export([greet_and_add_two/1]). add(A,B) ->
A + B. %%% Shows greeting.
%%% io:format/1 is the standard function used to output text. hello() ->
io:format("Hi Erlang!~n"). greet_and_add_two(X) ->
hello(),
add(X,2).

然后我们尝试编译并使用我们module:

> cd("C:/Users/zhenxingluo/Documents/Erlang").
C:/Users/zhenxingluo/Documents/Erlang
ok
> c(helloworld).
{ok,helloworld}
> helloworld:greet_and_add_two(3).
Hi Erlang!
5
> helloworld:module_info().
[{exports,[{greet_and_add_two,1},
{module_info,0},
{module_info,1}]},
{imports,[]},
{attributes,[{vsn,[251566447801502640269456451546098169641]}]},
{compile,[{options,[]},
{version,"4.8.1"},
{time,{2014,4,2,7,22,18}},
{source,"c:/Users/zhenxingluo/Documents/Erlang/helloworld.erl"}]}]

这里的cd是Erlang shell专用的一个函数,就是change directory。然后,我们调用Erlang shell中的编译函数c()。如果编译没有报错,我们就会看到helloworld.erl文件的旁边,有生成一个文件叫helloworld.beam。

事实上,beam代表Bogdan/Bjorn's Erlang Abstract Machine;这个VM只是众多Erlang的虚拟机之一,但是好像其他都不怎么用了。恩,继续编译没有报错的话,因为我们当前目录是helloworld.beam所在目录,所以,VM是看得见这个文件的。那么,我们就可以在shell窗口里直接调用他了。就像我们看到的那样。

这里的module_info()是编译器加入的一个函数,调用此函数可以查看我们module的metadata。同时,它也支持我们使用module_info/1,来查看其中的一项,比如,helloworld:module_info(attributes).

Erlang第三课 ---- 创建和使用module的更多相关文章

  1. 第三课 创建函数 - 从EXCEL读取 - 导出到EXCEL - 异常值 - Lambda函数 - 切片和骰子数据

    第 3 课   获取数据 - 我们的数据集将包含一个Excel文件,其中包含每天的客户数量.我们将学习如何对 excel 文件进​​行处理.准备数据 - 数据是有重复日期的不规则时间序列.我们将挑战数 ...

  2. Git速成学习第三课:创建与合并分支

    本来第三课想记录一下远程仓库的创建与克隆0.0但是想了想还是不写了. 这里写一下分支管理中的创建与合并. Git速成学习笔记整理于廖雪峰老师的官网网站:https://www.liaoxuefeng. ...

  3. CodeIgniter框架入门教程——第三课 URL及ajax

    本文转载自:http://www.softeng.cn/?p=74 这节课讲一下CI框架的路由规则,以及如何在CI框架下实现ajax功能. 首先,先介绍CI框架的路由规则,因为CI框架是在PHP的基础 ...

  4. NeHe OpenGL教程 第三课:颜色渲染

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. 【Linux探索之旅】第二部分第三课:文件和目录,组织不会亏待你

    内容简介 1.第二部分第三课:文件和目录,组织不会亏待你 2.第二部分第四课预告:文件操纵,鼓掌之中 文件和目录,组织不会亏待你 上一次课我们讲了命令行,这将成为伴随我们接下来整个Linux课程的一个 ...

  6. 【Web探索之旅】第二部分第三课:框架和内容管理系统

    内容简介 1.第二部分第三课:框架和内容管理系统 2.第二部分第四课预告:数据库   第二部分第三课:框架和内容管理系统 上一课我们介绍了服务器端的编程语言,有PHP,Java,Python,Ruby ...

  7. 【C++探索之旅】第一部分第三课:第一个C++程序

    内容简介 1.第一部分第三课:第一个C++程序 2.第一部分第四课预告:内存的使用 第一个C++程序 经过上两课之后,我们已经知道了什么是编程,编程的语言,编程的必要软件,C++是什么,我们也安装了适 ...

  8. 【C语言探索之旅】 第二部分第三课:数组

    内容简介 1.课程大纲 2.第二部分第三课: 数组 3.第二部分第四课预告:字符串 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语 ...

  9. 【C语言探索之旅】 第三课:你的第一个程序

    内容简介 1.课程大纲 2.第一部分第三课:你的第一个程序 3.第一部分第四课预告:变量的世界 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个 ...

随机推荐

  1. cocoaPod相关问题

    cocoap简介: 1. 简介 CocoaPods是一个负责管理iOS项目中第三方开源代码的工具,其源码在Github上开源.使用CocoaPods可以节省设置和更新第三方开源库的时间并提高工作效率. ...

  2. Linux Linux程序练习五

    题目:编写两个进程a和b,利用共享内存技术,a向共享内存写字符串,b将从共享内存中读到的字符串在屏幕上打印出来. //创建共享内存区 #include <stdio.h> #include ...

  3. An Introduction to Interactive Programming in Python (Part 1) -- Week 2_3 练习

    Mini-project description - Rock-paper-scissors-lizard-Spock Rock-paper-scissors is a hand game that ...

  4. css 兼容

    color:#0000FF\9; ;/*ie6,ie7,ie8*/ *color:#FFFF00;/*ie7*/ _color:#FF0000;/*ie6*/ body:nth-of-type(1) ...

  5. [CareerCup] 3.6 Sort Stack 栈排序

    3.6 Write a program to sort a stack in ascending order (with biggest items on top). You may use at m ...

  6. 熟悉linux开发环境(实验)

    北京电子科技学院(BESTI) 实验报告 课程: 深入理解计算机系统 班级: 1353班 姓名:张若嘉 杨舒雯 学号:20135330 20135324 成绩: 指导教师:娄嘉鹏 实验日期:2015. ...

  7. 移动统计工具Flurry

    网址:http://www.flurry.com/ 1注册和下载对应SDK 2集成SDK 3自定义统计项 至于怎么使用,后期会更新

  8. nodeJs--模块module.exports与实例化方法;

    在nodejs中,提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象.而在e ...

  9. 使用Let’s Encrypt轻松配置https站点

    使用Let's Encrypt轻松配置https站点 https不仅能提高网站安全,更是被搜索引擎纳入排名的因素之一. 2015年10月份,微博上偶然看到Let's Encrypt 推出了beta版, ...

  10. WP&Win10开发: RichTextBlock实现富文本并处理换行

    思路:1.构建字典.2.在字符串中匹配字典的key,将匹配到的key转换成对应的value3.将替换后的字符串,转化成xaml形式,加载该xaml以实现富文本. 代码如下: private Parag ...