《Erlang/OTP并发编程实战》第二章 Erlang语言精要

  1. erl -noshell

    启动Erlang系统,但是无法通过终端与启动后的Erlang系统交互。
    要执行批处理任务或要将Erlang作为守护进程时采用这个方法。

  2. shell函数:

    help()            打印可用的shell函数
    h()               打印先前输入过的命令
    v(N)              取出第N号提示符对应的计算结果
    cd(Dir)           Dir应是双引号字符串
    ls()
    ls(Dir)
    pwd()
    q()               init:stop()的简写
    i()               打印当前系统的运行时信息
    memory()          打印内存使用信息
  3. Erlang的数据类型:(项式)

    1. 数值

    2. 二进制串/位串

    3. 原子

    4. 元组

    5. 列表(包括字符串)

    6. 唯一标识符(pid、端口、引用)

    7. Fun函数

  4. 数值:

    扫描二维码关注公众号,回复: 9176273 查看本文章
    1. Erlang不允许浮点数以小数点开头

    2. 浮点数采用双精度浮点数

  5. 原子:

    1. 每个原子占一个字长的内存,原子的长度上限是255个字符;

    2. 小写字母开头,之后可以使用大写字母、数字、下划线、@;

    3. 如果需要用到其他字符,就得给它们加上单引号;

    4. 在单个系统中,原子的总数上限是一百多万(1048576),原子一经创建,即便不再使用也永远不会被清除,除非系统重启。

  6. 元组:

    1. 访问元组中的元素是常数时间复杂度的操作

  7. 列表:

    1. 引用透明性:被名称所引用的值不可更改;

    2. [] 被称为nil,它的值也只占一个字节的内存;

    3. ++ 运算符不关心右侧列表的长度;

    4. 底层实现是单链表,每个单元占两个字长内存;

    5. 列表主要用于存放临时数据,编排中间结果,或是用作字符串缓冲。对于需要长期存储的数据,如果尺寸因素很关键,就要考虑别的办法,比如用二进制串来存放较大的字符串常量数据。

  8. 引用:

    1. 可由 make_ref() 函数生成;

    2. 引用常被用做各种要求保证唯一性的一次性标签或cookie。

  9. 项式的比较:

    1. 列表 > 元组 > 原子 > 数值

    2. 相等比较:

      1. 完全相等 =:=

      2. 不完全相等 =/=

      3. 算数相等 ==

      4. 算数不等 /=

  10. 列表:

    1. 严格列表

    2. 非严格列表:在非列表数据之上堆叠列表单元而成的列表

  11. 函数调用:

    1. 远程调用:调用其他模块中的函数(不同于远程过程调用)

    2. 本地调用:调用同一模块中的函数

  12. 内置函数(BIF):涉及非常底层的内容,以致于不得不将它们集成到语言和运行时系统的内部,由C语言实现。

    1. erlang 模块中的所有函数都是 BIF;

    2. lists:reverse/1 也是BIF,为了追求执行效率;

    3. Erlang 语言中的运算符是 erlang模块的内置函数

  13. 模块的编译和加载:

    1. c(my_module)
      编译模块并加载模块

    2. 当Erlang尝试调用某个尚未加载到系统中的模块时,只要能找到与模块名对应的.beam文件,它就会自动尝试加载。

    3. code:get_path().         % 检查当前的代码路径设置
  14. 独立编译器 erlc

    1. erlc my_module.erl

    2. erlc -o ./ebin my_module.erl

  15. 不要用shell解释器来评测代码的执行效率。要想得出有意义的评测数据,就必须把代码写成模块。

  16. f().        % 让 shell 忘记之前绑定的所有变量
    f(X).       % 让 shell 忘记变量 X 的绑定
  17. ~p    % 将可打印字符列表显示为双引号字符串,如果项式过长而无法在一行内完整显示,便会分多行显示
    ~w    % 以原始的形态打印Erlang项式
  18. 远程别名 fun 函数:它们不依赖于被引用函数的特定版本。相反,在调用时,它们总是指向被引用函数的最新版本。

  19. Erlang 的异常:

    1. error:运行时异常,这些异常的特点在于一旦它们促使某个进程崩溃,Erlang 错误日志管理器便会将之记录在案。

    2. exit:通报“进程即将停止”,它们会在迫使进程崩溃的同时将进程退出的原因告知给其他进程,因此一般不捕获这类异常。exit 也在进程正常终止时使用,这时它会令进程退出并通报“任务结束,一切正常”。无论哪种情况,进程因 exit 而终止都不算是意外事件,因而也不会被汇报到错误日志管理器。

    3. throw:用于处理用户自定义的情况。如果进程没能捕获 throw 异常,它便会转变为一个原因为 nocatch 的 error 异常,迫使进程终止并记录日志。

  20. try...catch

    try
        some_unsafe_function()
    of
        0       ->    ...;
        N       ->    ...
    catch
    oops        ->    got_throw_oops;
    throw:Other ->    {got_throw, Other};
    exit:Reason ->    {got_exit, Reason};
    error:Reason->    {got_error, Reason}
    after
        file:close(FileHandle)
    end

    如果在 of 部分或 catch 部分抛出异常,该异常会被暂时挂起,直到 after 部分执行完毕后再被重新抛出。
    如果 after 部分又抛出异常,抛出的异常便会取代之前的异常,而原先被挂起的异常则会被丢弃。

  21. get_stacktrace().    % 获取当前进程的最近抛出的异常的栈轨迹
  22. 位串:

    1. <<Segment1,...SegmentN>>

    2. 区段指示符:(Data必须是整数、浮点数或另一个位串)

      1. Data

      2. Data:Size

      3. Data/TypeSpecifiers   (该类型决定了如何解读Data以及如何对它进行编解码,默认类型为 integer)

      4. Data:Size/TypeSpecifiers

    3. 区段的类型必须由你指定,不取决于 Data 自身的类型。

    4. 类型:(可以按多种方式由(-)组合,每组最多只能出现一种)

      1. integer、float、binary、bytes、bitstring、bits、utf8、utf16、utf32

      2. signed、unsigned

      3. big、little、native

    5. 位串速构:

      << <<X:3>> || X <- [1,2,3,4,5,6,7] >>.
      << <<X:8>> || <<X:3>> <= <<41,203,23:5>> >>.
      [ X || <<X:3>> <= <<41,203,23:5>> ].
  23. 预处理器:
    1. 条件编译:

      -ifdef(DEBUG).
      -export([foo/1]).
      -endif.

      shell 函数的 c 的 {d, MacroName, Value} 选项
      erlc 的 -Dname=Value

    2. 文件包含

      1. 查找路径:当前目录、包含路径内的目录

      2. 向包含路径内添加新目录:

        1. erlc 的 -I 标志

        2. shell 函数的 c("src/my_module", [ {i, "../include/"} ]).

        3. -include_lib 指令:

          1. 依赖于别的 Erlang 应用或库的头文件

          2. 该指令会兼容版本号的修改,很灵活,使用者不需要随各种变化来改动

    3. 宏展开

      1. 命名上,Erlang 变量和原子的命名规则都适用于宏

      2. 在正式编译前,代码中的宏会被展开

      3. 当无法用普通函数实现时,可以使用宏,比如:

        1. 必须确保在编译器展开某些代码

        2. 语法不允许执行函数

      4. 取消宏定义: -undef(foo)

      5. ?MODULE ?FILE ?LINE

  24. 进程监视:

    Ref = monitor(process, Pid).
  25. exit(Reason).
    exit(Pid, Reason).    // 收发双方无需链接,如果 Reason 是原子 kill,接收方将无法捕获该信号,从而被强制终止
    
    process_flag(trap_exit, true).    // 外来的退出信号会被转换成无害消息,除了无法捕捉的信号 kill 外
  26. receive
        Pattern1 when Guard1 -> Body1;
        ...
        PatternN when GuardN -> Body2N
    after Time
        TimeoutBody
    end.
    
    after...段:默认永不超时,单位毫秒,infinity,为0永不阻塞。
  27. 注册进程:

    registered().
    whereis(init).
    init ! {stop, stop}.
    
    registered_name ! Message.
    {node_name, registered_name} ! Message.

    假设某注册进程崩溃,对应的服务被重启,新服务进程的进程标识符将发生变化,此时,只需要更新进程注册表即可,但在服务完成重启和注册前,会存在一段真空期,期间该名称不指向任何进程。

  28. ETS:
    基本设计思想:尽量让它们的接口和行为与独立的进程一般无二。
    ETS 是作为 ERTS 的一部分用 C 实现的,既轻量又快速,接口函数也都是 BIF 。

  29. 尾调用优化:
    当编译器识别出尾调用(函数返回前的最后一个任务)时,会生成一段特殊的代码,这段代码会在执行尾调用之前从栈中扔掉当前调用的所有信息,此时当前调用基本无事可做,只需告知被调用的函数,计算结束后将结果告诉本函数的调用者即可。本质是:在必要时清理一些东西,然后执行跳转。

发布了42 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sanmao123456_/article/details/103223687