第二节 模块与函数(上)

模块

  模块是erlang的基本代码单元.模块保存在扩展名为.erl的文件里,而且必须先编译才能运行模块里面的代码.编译后的模块以.beam作为扩展名.

  我们创建一个geometry.erl的文件

1 -module (geometry).
2 -export ([area/1]).
3
4 area({rectangle,Width,Height})    ->    Width * Height;
5 area({square, Side})    ->    Side * Side.

  然后在shell中编译这个模块,并且运行它.

  1> c(geometry).
  {ok,geometry}
  2> geometry:area({rectangle, 10, 5}).
  50
  3> geometry:area({square,4}).
  16

  第一行c(文件名)的作用是编译文件里面的代码,运行成功会返回{ok,xxxxxx}这样的结果.同时生成一个.beam的目标代码模块.

  第二行我们通过文件名:方法(参数)的方式来调用模块中的函数.(请注意,需要给函数名附上模块名,这样才能准确标明想调用的是哪个函数).

  下一步,我们试着在模块中添加一些简单的测试模块.把之前那个模块命名为geometry_test.erl

 1 -module (geometry_test).
 2 -export ([test/0,area/1]).
 3
 4 test()    ->
 5     12 = area({rectangle, 3, 4}),
 6     144 = area({square, 12}),
 7     tests_worked.
 8
 9 area({rectangle,Width,Height})    ->    Width * Height;
10 area({square, Side})    ->    Side * Side.

  然后我们在shell中编译模块并且运行如果得到test_worked这样的字样就表示测试通过.

  1> c(geometry_test).
  {ok,geometry_test}
  2> geometry_test:text().
  ** exception error: undefined function geometry_test:text/0
  3> geometry_test:test().
  tests_worked

  如果在shell中输入错了函数名就会有错误提示.

  我们给之前的函数扩展一下增加一个area({circle, Radius})  ->  3.14159 * Radius * Radius. 要添加的子句,顺序无关紧要.无论子句如何排列,程序都是一个意思,因为子句里面的各个模式是互斥的.这就让我们编写扩展程序简单了很多.

  最后再看一下我们这个模块,我们会发现有逗号(,)分号(;)句号(.)这样的符号.

  逗号(,)分隔函数调用,数据构造和模式中的参数.

  分号(;)分隔子句.

  句号(.)分隔函数整体.

fun:基本的抽象单元

  erlang是一种函数式的编程语言.此外,函数式编程语言还表示函数可以被用作其他函数的的参数,也可以返回函数.操作其他函数的函数被称为高阶函数,而在erlang中用于代表函数的数据类型被称为fun.

  1.对列表里面的每一个元素执行相同的操作.

  2.创建自己的控制抽象.(erlang中没有for循环)

  3.实现可重入解析代码,解析组合器,或惰性求值器等事物.

  1> Double = fun(X) -> 2*X end.
  #Fun<erl_eval.6.54118792>
  2> Double(2).
  4

  上面就是在shell中定义一个fun的方法.

  下面我们看看定义2个参数是什么样的.

  3> Hypot = fun(X, Y)    ->      math:sqrt(X*X + Y*Y) end.
  #Fun<erl_eval.12.54118792>
  4> Hypot(3,4).
  5.0

  接下来我们以fun作为参数.标准库中lists模块导出了一些以fun作为参数的函数.他们之中最有用的就是lists:map(F,L).这个函数返回的是一个列表,它通过给列表L里的各个元素应用fun F生成.

  5> L = [1,2,3,4].
  [1,2,3,4]
  6> lists:map(fun(X) -> 2*X end, L).
  [2,4,6,8]

  另外一个有用的函数是lists:filter(P, L),它返回一个新的列表,内含L中所有符合条件的元素(条件是对元素E而言P(E)为true).

  Even = fun(X) -> (X rem 2) =:= 0 end.

  定义一个函数Even(X),如果X是偶数就返回true. rem会计算出除以2后的余数,=:=用来测试是否相等.

  然后我们用map和filter为参数.

  10> lists:map(Even, [1,2,3,4,5,6,8]).
  [false,true,false,true,false,true,true]
  11> lists:filter(Even, [1,2,3,4,5,6,8]).
  [2,4,6,8]

  函数不仅可以使用fun作为参数,还能返回fun.

  12> Fruit = [apple,pear,orange].
  [apple,pear,orange]
  13> MakeTest = fun(L) -> (fun(X) -> lists:member(X, L) end) end.
  #Fun<erl_eval.6.54118792>
  14> IsFruit = MakeTest(Fruit).
  #Fun<erl_eval.6.54118792>
  15> IsFruit(pear).
  true
  16> IsFruit(apple).
  true
  17> IsFruit(dog).
  false

  记住括号里面的东西就是返回值.

  下面我们来实现一个自定义的控制抽象,不过到目前为止erlang中我们还没有看见if语句,switch语句,for语句或者while语句,然后这一切都是用模式匹配和高阶函数编写的.我们自己实现一个for结构模块.

1 -module (lib_misc).
2 -export ([for/3]).
3
4 for(Max, Max, F)    ->    [F(Max)];
5 for(I, Max, F)        ->    [F(I) | for(I+1, Max, F)].

  然后在shell上执行这个模块

  1> lib_misc:for(1,10,fun(I) -> I end).
  [1,2,3,4,5,6,7,8,9,10]
  2> lib_misc:for(1,10,fun(I) -> I*I end).
  [1,4,9,16,25,36,49,64,81,100]

时间: 2024-10-11 11:50:09

第二节 模块与函数(上)的相关文章

第二节 模块与函数(下)

简单列表处理 上一节我们重点介绍了fun,现在我们继续编写sum和map,来改进我们之前实现的total总和的计算.新建一个mylists.erl 1 -module (mylists). 2 -export ([sum/1]). 3 4 sum([H | T]) -> H + sum(T); 5 sum([]) -> 0. 然后在shell上执行. 1> L = [1,3,10]. [1,3,10] 2> mylists:sum(L). 14 然后我们在原有的lists上增加一个

第二十四节,自定义函数

第二十四节,自定义函数函数是将要实现的功能写在函数里,在要使用此功能的地方调用此函数即可实现功能,这样大大减少编程重复书写同样的代码,在多个要使用同样功能的地方调用函数即可不需要重复写同样的代码函数式编程最重要的是增强代码的重用性和可读性 函数的定义主要有如下要点: def:表示函数的关键字函数名:函数的名称,日后根据函数名调用函数函数体:函数中进行一系列的逻辑计算,如:发送邮件.计算出 [11,22,38,888,2]中的最大数等...参数:为函数体提供数据return:返回值:当函数执行完毕

lua 中的上n级模块路径函数分享

在lua开发中使用模块并非难事也非易事,其中关于lua文件定位就不太直接方便. 比如有如下文件结构: 假设 me 是正在开发的模块.而由于 lua 中的 require 函数使用的相对于 lua 解释器的路径,同时 lua 也没有 ../ 这样的上一级文件的写法,所以如果 ti/me/pk/folder.lua 想要调用 ti/me/na 模块的话就必须写成出完整的路径出来.即floder.lua 中的调用语句就是 require (“ti.me.na”) . 但是如果me模块不是在 ti 文件

辛星让mysql跑得更快第二节之索引上部分

如果把我们的数据库信息当做一本书或者一个字典,那么索引可以理解为它的目录,如果我们创建一个优秀的目录,那么我们检索信息就会快得多,如果我们创建一个渣渣索引,也有可能拖垮整个系统. 索引我们分为四类,通常分为四大类型,即主键索引.全文索引.唯一索引.普通索引,这是按照索引的类型来分的.所谓主键索引,那就是当我们创建一张表的时候,如果我们指定了一个主键,那么它就自动成为主键索引,比如SQL语句如下(这里的id就自动成为了主键索引): create table xin(id int unsigned

辛星解读之php中的重点函数第一节之数组函数

这里我已经写好它的pdf版本了,比本博客更加适合阅读.首先说一下它在百度网盘的下载地址把:百度网盘下载 ,如果左边连接跪了,可以在浏览器中输入:http://pan.baidu.com/s/1qW5AYzM 来下载.然后说一下它在csdn的下载地址,是免积分的奥,下载地址:csdn资源下载处 ,如果连接不起作用,可以在浏览器输入:http://download.csdn.net/detail/xinguimeng/7697309  来手动下载. 好,我们知道php中函数还是很多的,正是这些函数为

VB6/VBA中跟踪鼠标移出窗体控件事件(类模块成员函数指针CHooker类应用)

前几天发了一篇博文,是关于获取VB类模块成员函数指针的内容(http://www.cnblogs.com/alexywt/p/5880993.html):今天我就发一下我的应用实例. VB中默认是没有鼠标移出事件响应的,而这个事件其实在项目开发中,实用性很强,很多时候需要在鼠标移出窗体或控件时做些事情:没有这个事件会感觉很费力: 今天我所说的实际案例就是,在窗体上,设计一个SplitterBar控件,窗体的最终用户使用这个控件可以在运行程序时任意调整其内部控件大小. 我在第二篇参考博文作者开发的

【p2】&#183;python中嵌套列表list元素输出&#183;模块封装&#183;发布上传(pigeon详细说)

如果你也正在学习<Head First Python>,可以相互学习.接下来将记录如何完成书本的这一章以及遇到的问题如何解决. 一.简单访问列表数据 [1]通过位置访问具体数据,0表示第一位[如下图] [2]计算列表长度[使用len] [3]列表末尾增加--删除元素,append增肌,pop删除,注意不同用法 append括号里放想添加元素,列表.pop()就能删除 [4]extend添加多个元素[如想在后面添加5,6,7],留意跟append区别 append保留着数据项中括号,缺陷 ---

【读书笔记】《鸟哥Linux私房菜-基础知识篇》第二节 基础命令

第二节 基础命令 uname –r 查询Linux核心版本. 装置及装置在Linux内的文件名 IDE硬盘机 /dev/hd[a-d] SCSI/SATA/USB硬盘机 /dev/sd[a-p] USB快闪碟 /dev/sd[a-p] 软盘驱动器 /dev/fd[0-1] 打印机 25针:/dev/lp[0-2] USB:/dev/usb/lp[0-15] 鼠标 USB:/dev/usb/mouse[0-15] PS2:/dev/psaux 当前CDROM/DVDROM /dev/cdrom 当

2014年度辛星css教程夏季版第二节

第一节我们简介了一下CSS的工作流程,我相信读者会有一个大体的认识,那么接下来我们将会深入的研究一下CSS的细节问题,这些问题的涉及将会使我们的工作更加完善. *************注释************ 1.CSS也是需要注释的,注释中的内容不会被解释执行,它也和C语言一样,用/*开头,用*/结尾,其中的内容会被当做注释,我们想怎么写就怎么写. 2.下面给个例子: p{ color: green; /* 我们在这里书写注释 * 辛星CSS,与博客园共同成长 */ font-size: