文档章节

Erlang if、case、guard和函数

leeyi
 leeyi
发布于 2016/08/10 11:25
字数 1703
阅读 39
收藏 0
点赞 0
评论 1

Erlang 函数、if、case、guard

每节排版顺序:伪代码,说明文字,案例

函数

伪代码

%单一语句的的函数
function_name(Param1, Param2, ..., ParamN) ->
    Expression1, Expression2, ..., ExpressionN.

%多语句的函数,其中每条语句的参数个数应该是一样的
function_name(Param11, Param12, ..., Param1N) ->
    Expression11, Expression12, ..., Expression1N;
function_name(Param21, Param22, ..., Param2N) ->
    Expression21, Expression22, ..., ExpressionN2;
...
function_name(ParamN1, ParamN2, ..., ParamNN) ->
    ExpressionN1, ExpressionN2, ..., ExpressionNN;

函数的名称是一个基元。一个函数的头包括名字,随后是一对括号,在里面包含多个形式的参数或者没有参数。在Erlang中,函数参数的数量叫做元数。使用箭头(->)来分隔函数头和函数主体。

Erlang函数是由分号分隔开的一个或者多个语句组成的,最后用句点来结束。每一个语句都有一个头部用来指定期望的参数模式,还有一个函数体,它由一个或多个以逗号分隔开的表达式组成,这些语句逐一按序执行,函数的返回值是最后一个表达式的结果。

案例

%一个计算形状面积的Erlang函数

area({ square, Side}) ->
    Side* Side;
area({ circle, Radius}) ->
    math:pi() * Radius * Radius;
area({ triangle, A, B, C}) ->
    S = ( A  B  C)/ 2,
    math:sqrt(S*(S-A)*(S-B)*(S-C));
area( Other) ->
    {error, invalid_ object}.

if 结构

伪代码

if
    Condition1 ->
        Expression11, Expression12, ...;
    Condition2 ->
        Expression21, Expression22, ...;
    Condition3 ->
        Expression31, Expression32, ...;
    ...;
    ConditionN ->
        ExpressionN1, ExpressionN2, ...
end

Erlang是这样工作的:先对Condition1求值,如值为true,那么将执行Expression11, Expression12, ...;并跳出该结构。若Condition1不成功,那么就继续对Condition2求值,以此类推,直到有条件成功。在if结构中,必须要有一个结果为true,否则Erlang就会抛出一个异常。通常if语句的最后一个条件会是原子true,表示如果没有匹配的条件的话,应该做什么动作。

整个if表达式的结果是上面这一系列语句的返回值,它就是被执行的分支中最后执行语句的计算值。

案例

     %前面面代码省略 func_common 就不贴出来了
    IsEmail    = func_common:is_email(LoginId),
    IsMobile   = func_common:is_mobile(LoginId),
    IsNickname = func_common:is_nickname(LoginId),
    Conditions = if
        IsEmail ->
            [{email, LoginId}];
        IsMobile ->
            [{mobile, LoginId}];
        IsNickname ->
            [{nickname, LoginId}];
        true ->
            [{nickname, LoginId}]
    end,

    Member = boss_db:find(member, Conditions),
    %后面代码省略
%% if 语句
compare(A, B) ->
    if A > B ->
            io:format("~p > ~p~n", [A, B]);
        A < B ->
            io:format("~p < ~p~n", [A, B]);
        true ->
            io:format("~p = ~p~n", [A, B])
    end.

case 结构

伪代码

case conditional-expression of
    Pattern1 ->
        Expression1;
    Pattern2 ->
        Expression2;
    ...;
    PatternN ->
        ExpressionN
end

case结构依靠模式匹配来判断应该执行哪些语句,它跟通过模式匹配来选择执行函数很类似。不同的是,case不是把函数的真实参数和形式参数进行模式匹配,而是通过对一个表达式求值,然后对它的结果和一个由分号隔开的模式匹配列表进行匹配。

使用的关键字是case、of和end。对conditional-expression求值,然后和Pattern1,...,PatternN进行匹配,直到第一个模式匹配成功。->符号把语句的模式或者头部与由逗号分隔的表达式列表组成的主体分开。一旦模式匹配成功,选中的语句表达式就会一个个按次序执行,case结构的结果就是最后一个表达式的运行结果。

与函数定义一样,case表达式的结果必须和一个模式匹配,否则将会得到一个运行时错误。如果在最后的模式中有_或者未绑定变量,那么它将匹配任何Erlang项元,这就如我们在第2章中讨论的catch-all语句一样。catch-all语句不是必需的,事实上,不鼓励把它作为一种防错性编程的形式来使用。

案例

%% case 语句
compare3(A, B) ->
    case A > B of
        true ->
            io:format("~p > ~p~n", [A, B]);
        _ ->
    case A < B of
        true ->
            io:format("~p < ~p~n", [A, B]);
        _ ->
            io:format("~p = ~p~n", [A, B])
    end
end.

guard 结构

伪代码

function_name(Param1, Param2, ..., ParamN) when Condition1 ->
    Expression1;
function_name(Param1, Param2, ..., ParamN) when Condition2 ->
    Expression2;
...
function_name(Param1, Param2, ..., ParamN) when ConditionN ->
    ExpressionN.

保护元( guard)是一个额外的限制条件,它应用于函数的case或者receive语句中。保护元应该放在“->”之前来分隔语句的主体和头部。 保护元由when关键字和紧跟其后的一个保护元表达式组成。只有在模式匹配和保护元表达式求值结果为基元true的情况下,这个语句才会执行。

单独的保护元表达式可以使用如下的结构获得:

  • 约束变量·Erlang常量的数据值,包括数字、基元、元组和列表等
  • 类型测试语句,比如is_binary、is_atom、is_boolean和is_tuple等
  • 第2章中所列出的项元比较运算符==、=/=、<、>等
  • 第2章中所列出的使用算术运算符组成的算术表达式
  • 第2章中所列出的布尔表达式

保护元内置函数导致运行时错误的保护元子表达式被视为返回false。

<b>保护元可以是测试的复杂组合,但并不允许引用任何用户自定义的函数。 </b>

规定开发人员不能用语句实现自己的保护元函数的原因是要限制它们的操作,从而确保保护元语句不会产生边界效应。在找到一个成功的语句执行之前,将会执行所有的测试保护元语句,这意味着假设在一个保护元里调用一个io:format,如果它失败了,你还是会看到打印输出,即使这个语句没有被选中执行。

<b>注意:</b>在Erlang语言中有一些类型测试内置函数的老版本,它们的名称就是类型名称:atom/1和integer/1等。不推荐使用这些内置函数,因为它们已经过时,它们的存在只是为了向后兼容。新的保护元函数是is_atom/1和is_integer/1等。

Erlang允许保护元进行简单的逻辑组合,以不同的方式实现:

  • 用逗号(,)来分隔各个保护元语句,这是一种逻辑乘,因此只有在串行序列中所有表达式的值都是true的时候,它的结果才为true。
  • 用分号(;)来分隔各个保护元语句,这是一种逻辑加(或者实际上是逗号分隔的逻辑乘),如果有一个表达式的值为true,则它的结果就是true。

案例

my_add(X, Y) when not( ((X>Y) or not(is_atom(X))) and (is_atom(Y) or ( X==3.4)) ) ->
    X+Y.
max(X, Y) when X > Y
    -> X;
max(X, Y) ->
    Y.
factorial(N) when N>0 ->
    N * factorial(N-1);
factorial(0) ->
    1.
-module(compare).

-export([compare/2, compare2/2, compare3/2]).

%% guard 语句
compare2(A, B) when A > B ->
    io:format("~p > ~p~n", [A, B]);
compare2(A, B) when A < B ->
    io:format("~p < ~p~n", [A, B]);
compare2(A, B) ->
    io:format("~p = ~p~n", [A, B]).

© 著作权归作者所有

共有 人打赏支持
leeyi
粉丝 5
博文 46
码字总数 52465
作品 0
深圳
后端工程师
加载中

评论(1)

leeyi
leeyi
如果有错别字,或者案例有问题,欢迎留言反馈
[Erlang 0011] Erlang 杂记Ⅱ

学习Erlang的时候在书的留白处随手记录了一些东西,还有一些记录在了demo的注释里面,今天又整理出来了一部分,分享一下. 上一次的地址:[Erlang 0009] Erlang 杂记 Erlang属于面向消息的语言,面...

唐玄奘
2017/12/03
0
0
Swift 2.0 异常处理

Swift 2.0 异常处理 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法。这篇文章会主要围绕这个方面进行讨论。 如何建造异常类型? 在 iOS 开发当中,我们会面...

法斗斗
2016/03/01
6
0
转载:Erlang 函数(Efficiency Guide)

转自:http://www.cnblogs.com/futuredo/archive/2012/10/26/2737644.html Functions 1 Pattern matching 模式匹配 Pattern matching in function head and in case and receive clauses ar......

宁静_夏天
2013/12/12
0
0
c(tuples1). tuples1.erl:20: illegal guard expression

erl 编译之后报错, 我本意是: showPerson/1 函数输出 用户信息,他的参数要么是 元祖 {Name, Age, Phone} 要么是 记录 -record (person, {name, age=0, phone=""}). 求指点,给个争取的实现...

leeyi
2015/10/12
158
1
[Erlang 0120] Know a little Core Erlang

Erlang开发者或多或少都用过或者听说过Core erlang,它是什么样的呢?新建一个测试模块a.erl,如下操作会生成core erlang代码而非a.beam: 这时文件夹中已经生成了一个a.core的文件,然后我们如下...

唐玄奘
2017/12/08
0
0
Swift 个人学习笔记 - 06: 控制流

本文章纯粹是中文版《The Swift Programming Language》的学习笔记,所以绝大部分的内容都是文中有的。本文是本人的学习笔记,不是正式系统的记录。仅供参考 以下还是有很多没看懂、不确定的...

amc
2017/02/22
0
0
Erlang语言研究综述

摘 要: 本文前半部分主要是关于Erlang编程语言相关的内容;着重就一般学习编程语言的一般的关注点来阐述了Erlang编程语言的基本语法点,主要包括:Erlang的变量、Erlang的数据类型、Erlang的...

zhangwenwen
2015/09/27
79
0
[Erlang 0018]Erlang为何对List情有独钟?

Erlang编程实践中绝大多数时候是在和List打交道:取头元素,遍历,匹配...为什么Erlang和其它函数式编程的语言都对对List情有独钟呢?《Erlang and OTP in Action》一书的附录B中提到了这个问题,...

唐玄奘
2017/12/03
0
0
04-Swift逻辑分支

逻辑分支 一. 分支的介绍 分支即if/switch/三目运算符等判断语句 通过分支语句可以控制程序的执行流程 二. if分支语句 和OC中if语句有一定的区别 判断句可以不加() 在Swift的判断句中必须有明...

不孤独的美食家
2016/08/05
7
0
Swift讲解专题六——流程控制

Swift讲解专题六——流程控制 一、引言 一种编程语言的强大与否,很大程度上取决于其提供的程序流程控制方案,就如使用汇编语言实现复杂的程序流程是一件痛苦的事情。Swift中提供了许多强大的...

珲少
2016/05/12
383
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
2
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
1
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
158
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部