Erlang基础(三):异常,BIF,比特语法,编译与运行

开篇

恩,被赤裸裸的打脸了,刚说完每周2更,结果拖到现在都没有一更。。恩。。虽然中间本人完成了人生大事的一部分--订婚。
好了,废话不多说,今天来介绍下 异常,内置函数,二进制数据和所对应的比特语法,以及如何编译和运行程序等等。

异常

  • 简介
    关于异常,其实在传统的编程语言里面使用的比较多,诸如:Java,C#。恩,C和C++是个例外。在erlang中,异常捕获的语法也大同小异.
try ... of
  Pattern [when guard] -> expression;
  ...other pattern...
catch
  exception type : Pattern [when guard] -> express;
  ...other pattern...
after
  expression;
  ...other expression...
end.
  • 异常捕获
    其中,try ... of 中是需要捕获异常的表达式或者函数。函数或者表达式的值,会逐步与 of 下面的模式进行匹配,并给出匹配到的表达式的值。
    在catch中,捕获异常类型。erlang定义的异常类型只有三种:
  throw-> 调用者处理的可忽略的异常,
  exit-> 程序退出类型异常,
  erlang:error -> 程序崩溃类型异常
  • Final Handling
    after处的表达式不论异常是否捕获,均会处理。根据传统语言的编程经验来看,此处比较适合处理资源释放,如:数据库连接释放,文件释放等等。

  • demo
    光说不练假把势,写一个捕获所有可能产生异常的函数,以及写一个产生所有异常的函数进行测试:


    Erlang基础(三):异常,BIF,比特语法,编译与运行_第1张图片
    demo1

    可以先忽略test2函数,稍后会说到。generate_exception/1 函数会产生一个函数被调用时所有可能出现的结果,catcher/1 函数尝试对这些结果进行异常捕获或者正常处理。test/0 函数将这些结果合并到一个列表中。

  • 另外一种写法
    当然,捕获异常还有另外一种写法:

catch expression.

直接捕获表达式中的异常.如 demo 代码中的 test2/0 函数.

  • 编程规范
    捕获异常还是有几种best practise的。如:
  1. 经常会返回错误的程序
  case ... of 
      {ok, Val} -> do_something(Val);
      {error, Why} -> %% do something with error message Why
 end.
  2. 出错几率小的代码
  try ...
  catch
    throw:{thisError, Val} -> ...
    exit:{otherError, Val} ->...
  end.
 3. 捕获所有可能的异常
  try expression
  catch
    _:_ -> ... %% 切记,此处不能写成 _ -> 。如此则捕获不到任何异常.
  end.

BIF

BIF 即 Built in functions,也就是内置函数,或称之为系统函数更为合适些。erlang中的BIF看起来像是函数,其实不然,他是针对于erlang虚拟机的操作指令。如:

@spec time() -> 获取当前时间

@spec lists:reverse(List) -> List. 翻转列表

@spec term_to_binary(Term) -> binary().  将所有erlang的值转换为二进制数据.n

注: @spec 为erlang中的文档标记用法

比特语法

  • 简介
    比特语法主要用于处理二进制数据,经常用于对于单个比特位或者比特位串进行封包或者解包。

  • Examples

%%解析COFF数据
-define(DWORD, 32/unsigned-little-integer).
-define(LONG, 32/unsigned-little-integer).
-define(WORD, 16/unsigned-little-integer).
-define(BYTE, 8/unsigned-little-integer).
<>.

上述代码参照COFF的结构体进行二进制数据读取,可见,尤为简单。无需移位,截断等等。

编译运行

运行的方式大致有三种,shell中运行,单文件编译运行,工程编译运行。

  • 运行环境设置
    erlang虚拟机自动加载模块时,首先要指定模块文件所在的路径,两种方式,可以在启动时,通过 -pa, -pz指定添加。pa 为加载搜索路径的头,pz 为加载搜索路径的末尾。也可以在 目录下的.erlang文件中,通过2个BIF添加 @spec code:add_patha(Dir), @spec code:add_pathz(Dir)前者加入到搜索路径的头,后者加入到搜索路径的末尾。如:
io:format("Allen@erlang virtual machine~n").
code:add_pathz(".");

运行结果:


Erlang基础(三):异常,BIF,比特语法,编译与运行_第2张图片
  • shell运行
    shell运行时,如果需要退出,最佳方案是使用 q(). 方式进行退出,而不是erlang:halt(). 如果使用 erlang:halt(). 会使得部分程序(数据写入等)产生错误修复,再下一次启动时.
    若shell不允许输入时,只能通过杀掉进程的方式停止运行。注意,如果erlang程序是以 -heart Cmd 的方式启动,启动时会带上监控进程,监控进程在进程死亡时会执行Cmd,若Cmd的指令为重启程序,那么首先要杀掉这个监控进程。

  • 单文件编译运行
    可以在shell中,使用 c(filename).进行编译,然后使用模块对应的函数。如:

-module (hello).
-export([hi/0]).
-auth(allen).
-date("2015.08.28").
-vsn("1.0.0").
hi () ->
    "Hello World".

执行方式:


Erlang基础(三):异常,BIF,比特语法,编译与运行_第3张图片

也可以在命令行下编译并执行,如:

erlc hello.erl
erl -noshell -s hello hi -s init stop

结果:


Erlang基础(三):异常,BIF,比特语法,编译与运行_第4张图片

当然,还有一种方式则是编写 escript 或者 编写sh脚本运行程序。(使用 -eval 命令)--> 限于篇幅,将在后续IM工程中使用时介绍。

  • makefile
    赞叹下,makefile不愧为工程神器。从cpp,到erlang,到ELisp,到...。真是太赞了。
    所以,erlang的makefile写法与cpp的也没啥区别。
    下面列出一个简要的模板:
.SUFFIXES: .erl .beam
.erl.beam:
    erlc -W $<
ERL = erl -boot start_clean
MODS=hello
all: compile
    ${ERL} -pa "." -s hello hi
compile: ${MODS:%=%.beam}
clean:
    rm -rf *.beam erl_crash.dump

执行结果如下:


Erlang基础(三):异常,BIF,比特语法,编译与运行_第5张图片
makefile
  • rebar
    当然,编写makefile也有点麻烦,业界比较好用的工具有个rebar。rebar不单单可以进行工程的编译,还可以创建工程模块,以及发布等等。非常强大。
    此处不做赘述,请移步Github

你可能感兴趣的:(Erlang基础(三):异常,BIF,比特语法,编译与运行)