Progamming Erlang 笔记 - 第 4 章 模块与函数

版权声明:@潘广宇博客, https://blog.csdn.net/panguangyuu/article/details/89097311

第4章 模块与函数

4.1 模块是存放代码的地方

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

② 函数的模式匹配

-module(geometry).
-export([area/1]).

area({rectangle, Width, Height}) -> Width * Height;
area({square, Side})             -> Side * Side.

% area函数有两个字句,字句以分号隔开,最后的字句以句号加空白结束。

4.1.1 常见错误

① c(geometry). 等只能在shell工作,不能放入模块

② 碰巧使用了与系统模块冲突的模块名,在编译时会报不能加载:stick directory (固定目录) 的错误

4.1.2 目录与代码路径

  • pwd() : 打印当前目录
  • ls() :列出当前目录所有文件名
  • cd(Dir) : 修改当前目录为Dir

4.1.3 给代码添加测试

-module(geometry).
-export([test/0, area/1]).

test() -> 
    12 = area({rectangle, 3, 4}),   

    % 当函数返回12时,与12匹配,不会报错,test()函数返回test_worked

    test_worked.

area({rectangle, Width, Height}) -> Width * Height.

4.1.5 分号放哪里

  • 逗号(,)分隔函数调用,数据构造,模式中的参数
  • 分号(;)分隔字句,如函数定义,case,if等表达式
  • 句号(.)分隔函数整体与shell里的表达式

4.2 继续购物

编写程序计算购物所花的费用

商店 shop 模块:

-module(shop).
-export([cost/1]).

cost(oranges) -> 5;
cost(apple) -> 10.

假设购物列表:

buylist = [{orange, 4}, {apple, 2}]   % 4、2 表示分别购买的数量

计算费用模块:

-module(counter).
-export([total/1]).

total([{What, N} | T]) -> shop:cost(What) * N + total(T);
total([])              -> 0.

4.3 基本的抽象单元

① 操作其他函数的函数被称为高阶函数,Erlang 中函数数据类型为 fun

Double = fun(X) -> 2 * X end.

> #Fun <erl_eval.6.5....>

Double(2)

> 4

4.3.1 以fun作为参数的函数

L = [1, 2, 3, 4]

lists:map(fun(X) -> 2*X end, L).

> [2, 4, 6, 8]

4.3.2 返回fun的函数

Fruit = [apple, pear].

MakeTest = fun(L) -> (fun(X) -> lists:member(X, L)  end) end.

IsFruit = MakeTest(Fruit).

IsFruit(pear).

> true

4.3.3 定义你自己的控制抽象

for(Max, Max, F) -> [F(Max)];
for(I, Max, F)   -> [F(I) | for(I+1, Max, F)].

% 执行for(1, 10, fun(I) -> I end) 会得到 [1,2, ... 10]

4.4 简单的列表处理

-import(lists, [map/2, sum/1])     % 从lists模块导入map,sum函数,可直接使用map(Fun,...)来代替lists:map(Fun, ...)

4.5 列表推导

① 列表推导是一种快速创建列表的表达式

② 语法:[ F(X) || X <- L ] ,由F(X)组成的列表,X从列表L中提取。

[ X || Qualifier1, Qualifier2, ... ]  ,限定符 Qualifier 可以是:

1)生成器,Pattern -> List

2)位串,BitStringPattern <= BitStringExpr

3)filter,可以是判断函数(返回true/false),或布尔表达式

如:[ X || {a, X} <- [ {a, 1}, {b, 2}, ... {a, 4}, hello ] ].                            % 返回 [1, 4]

4.5.1 QuickSort

快速排序实现:

qsort([]) -> [];
qsort([Pivot | T]) -> 
    qsort([X || X <- T, X < Pivot ]) ++ [Pivot] ++
    qsort([X || X <- T, X >= Pivot ]).

% ++ :中缀插入操作符

4.5.2 毕达哥拉斯三元数组

pythag(N) -> 
    [ {A, B, C} || A <- lists:seq(1, N), 
                   B <- lists:seq(1, N),
                   C <- lists:seq(1, N), 
                   A + B + C =< N,
                   A*A + B*B + C*C =:= C*C ].

4.5.3 回文构词

perms([]) -> [ [] ];
perms(L)  -> [ [H|T] || H <- L, T <- perms(L -- [H]) ].

% 以L="cats"为例,X -- Y 是列表移除符,从X里移除Y中的元素

% 第一次 H1 = C, T1 <- perms("ats") : H11 = a, T11 <- perms("ts") : ...
                                     H12 = t, T12 <- perms("as") : ...
                                     H13 = a, T13 <- perms("at") : ...

% 所以:c 开头:cats cast ctas ctsa csat csta,以此类推到c\a\t\s开头

4.7 关卡

max(X, Y) when X > Y -> X;
max(X, Y)            -> Y.

% 在函数定义里的头部使用关卡(通过when引入)

4.7.2 关卡示例

f(X, Y) when is_integer(X), X > Y,  Y < -6 -> ...

% 当X是一个整数,X大于Y并且Y小于-6时函数执行

X =:= dog ; X =:= cat 

% X 是一个cat或是一个dog成立

4.7.3 true关卡的作用

if 
    Guard -> Expr1;
    Guard -> Expr2;
    ...
    true  -> Expr
end.

4.8 case与if表达式

4.8.1 case表达式

case Expression of 
    Pattern1 [ when Guard1 ] -> Expr1;
    Pattern2 [ when Guard2 ] -> Expr2;
    ...
end

4.8.2 if表达式

① 必须至少有1个关卡执行结果为true,否则会发生异常错误

② 设最后一个关卡是原子true,确保其他关卡失败时表达式最后会被执行。

4.10 归集器

求列表中的奇数与偶数,原始程序:

odds_and_evens(L) ->
    Odds = [ X || X <- L, (X rem 2) =:= 1 ], 
    Evens = [ X || X <- L, (X rem 1) =:= 0 ],
    {Odds, Evens}. 

% 这个程序的问题:遍历了列表两次
% 通过 case 语句实现只遍历1次

odds_and_evens(L) -> odds_and_evens_acc(L, [], []).

odds_and_evens_acc([H | T], Odds, Evens) ->
    case (H rem 2) of
        1 -> odds_and_evens_acc(T, [H | Odds], Evens);
        0 -> odds_and_evens_acc(T, Odds, [H | Evens])
    end;
odds_and_evens_acc([], Odds, Evens) -> {Odds, Evens}.

% 现在程序只遍历1次,把奇偶分别添加到合适的列表中。这些列表称为归集器(accumulator),更节省空间。

猜你喜欢

转载自blog.csdn.net/panguangyuu/article/details/89097311
今日推荐