作者 Joe Armstrong(27 December 1950 – 20 April 2019)’s blog

  • https://joearms.github.io
  • http://armstrongonsoftware.blogspot.com

资料

Basic

hello.erl

-module(hello).
-export([start/0]).

start() ->
    io:format("Hello world~n").
	
  • erl shell
$ erl
Erlang/OTP 22 [erts-10.4.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

Eshell V10.4.4  (abort with ^G)
1>

  • = 模式匹配

    test & bind

    f()释放所有绑定

  • 模块

    扩展名为 .erl 的文件

  • 编译

    erlang shell

    1> c(module_name)

    shell

    $ erlc hello.erl

  • 运行

    erlang shell

    2> hello:start()

    shell

    $ erl -noshell -s hello start -s init stop

  • 进程

    3> Pid = spawn(hello,start,[]).

  • self()

    获取当前进程的 Pid

  • !

    往进程信箱投递消息

    5> Pid ! “hello”.

  • receive

      loop(Dir) ->
          receive
              {Client, list_dir} ->
                  Client ! {self(), file:list_dir(Dir)};
              {Client, {get_file, File}} ->
                  Full = filename:join(Dir, File),
                  Client ! {self(), file:read_file(Full)}
          end,
          loop(Dir).
    

    作者利用分布式的 Erlang 节点 实现一个文件传输服务器: 为什么我经常从零开始实现一个东西

  • erl shell 中的快捷键

    C-c C-g

  • 变量

    大写字母开头

    一次性赋值 –> 无可变状态 –> 无共享内存 –> 无锁

    模式匹配、变量绑定

  • / div rem

    5/2 –> 2.5 浮点数

    5 div 2 –> 2

    5 rem 2 –> 1

  • 浮点数

    Erlang在内部使用64位的IEEE 754-1985浮点数

  • 原子

    全局

    小写字母开头

    单引号内大写字母开头或非字母数字外的字符

    Erlang不会垃圾回收(garbage collect)原子

  • 元组

    把一些数量固定的项目归组成单一的实体

    声明它们时自动创建

    创建 、 析取

     15> X = {joe, {name, "joe"}, {age, 69}}.
     X = {joe, {name, "joe"}, {age, 69}}.
    
     17> {_,{_, Name},{_,Age}} = X.
     {_,{_, Name},{_,Age}} = X.
     {joe,{name,"joe"},{age,69}}
    
     18> Name.
     Name.
     "joe"
    
     19> Age.
     Age.
     69
    
    
  • 列表 [head tail]

    用来存放任意数量的事物

    表头 head 一个项目

    表尾 tail 也是一个列表

    空列表 []

    给tail 列表的开头添加不止一个元素 [E1,E2,..,En tail]

    创建、析取

     21> T = [X,X,X, 1 + 2, "hello", 2.5, joe, {p,"test"}].
     T = [X,X,X, 1 + 2, "hello", 2.5, joe, {p,"test"}].
     [{joe,{name,"joe"},{age,69}},
      {joe,{name,"joe"},{age,69}},
      {joe,{name,"joe"},{age,69}},
      3,"hello",2.5,joe,
      {p,"test"}]
     22> T2 = ["H1","h2", 3 | T].
     T2 = ["H1","h2", 3 | T].
     ["H1","h2",3,
      {joe,{name,"joe"},{age,69}},
      {joe,{name,"joe"},{age,69}},
      {joe,{name,"joe"},{age,69}},
      3,"hello",2.5,joe,
      {p,"test"}]
    
     23> [H1,H2,H3,  {_,{_, Name1},{_,Age1}},  {_,{_, Name2},{_,Age2}} | T3] = T2.
     [H1,H2,H3,  {_,{_, Name1},{_,Age1}},  {_,{_, Name2},{_,Age2}} | T3] = T2.
     ["H1","h2",3,
      {joe,{name,"joe"},{age,69}},
      {joe,{name,"joe"},{age,69}},
      {joe,{name,"joe"},{age,69}},
      3,"hello",2.5,joe,
      {p,"test"}]
     24> H1.
     H1.
     "H1"
     25> H2.
     H2.
     "h2"
     26> Name1.
     Name1.
     "joe"
     27> Name2.
     Name2.
     "joe"
    
    
  • 字符串

    Erlang里没有字符串

    表示方法:

     整数组成的列表( 每个元素为 unicode codepoint 代码点)
    	
     二进制类型
    
     字符串字面量 -- 双引号 围起来的一串字符 "hello" --  列表简写模式
    

    列表内的 所有 整数 都为可打印字符时,打印出来的是字符串字面量,反之为列表

    列表表示字符串时,每个整数代表对应的 Unicode 字符, 无穷大字符 – "a\x{221e}b"

    格式化输出

     - 输出 unicode 字符 erl shell 为 Latin 字符集,回显显示的是整数列表形式
     - 字符串按照列表形式输出
    
         Erlang/OTP 22 [erts-10.4.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]
    
         Eshell V10.4.4  (abort with ^G)
         1>  X2 ="a\x{221e}b".
         [97,8734,98]
         2> io:format("~ts~n",[X2]).
         ab
         ok
        
         4> X1 = [97, 98, 99].
         "abc"
         5> X = "abc".
         "abc"
    		
         9> io:format("~p~p~n", [X,X1]).
         "abc""abc"
         ok
         10> io:format("~p~w~n", [X,X1]).
         "abc"[97,98,99]
         ok
    

    字符—>整数 $A %% 96

  • case

  • 标点符号 , ; .

  • try

  • fun

  • 列表推导

  • BIF 内置函数 属于 模块 erlang http://erlang.org/doc/man/erlang.html

  • guard : when : , ; – erlang 表达式子集

  • 记录

    记录其实就是元组的另一种形式,因此它们的存储与性能特性和元组一样

    -record(todo , {status = reminder, who=joe, text})

    rr("record.hrl") 读取记录定义

    构建 直接创建 基于旧的创建 析取 模式匹配

  • 映射

    #{a => 1, b:2}

    maps模块 操作映射组的内置模块

    构建 直接创建 基于旧的创建 析取 模式匹配

    比较

      大小
      按照建的排序,比较键值的大小
    
    	
      2> #{age=>20, name:="yang", friends:=[#{name:="A",age:=21},#{age:=19,name:="B"}]}.
      * 1: only association operators '=>' are allowed in map construction
      3> #{age=>20, name=>"yang", friends=>[#{name=>"A",age=>21},#{age=>19,name => "B"}]}.
      #{age => 20,
        friends =>
            [#{age => 21,name => "A"},#{age => 19,name => "B"}],
        name => "yang"}
      4> X1 = #{age=>20, name=>"yang", friends=>[#{name=>"A",age=>21},#{age=>19,name => "B"}]}.
      #{age => 20,
        friends =>
            [#{age => 21,name => "A"},#{age => 19,name => "B"}],
        name => "yang"}
      5> X2 = X1#{name:="test"}.
      #{age => 20,
        friends =>
            [#{age => 21,name => "A"},#{age => 19,name => "B"}],
        name => "test"}
    
      6> X1 >X2 .
      true
      7> X1 < X2.
      false
      8> maps:to_list(X1).
      [{age,20},
       {friends,[#{age => 21,name => "A"},
                 #{age => 19,name => "B"}]},
       {name,"yang"}]
      9> maps:to_list(X1) > maps:to_list(X2).
      true
    

    黑历史:https://stackoverflow.com/questions/27803001/undefined-function-mapsto-json-1

  • 异常 错误

    • 典型系统内部产生错误: 模式匹配失败

    • 使用函数主动产生错误

      throw(Exception)

      exit(Exception)

        终止当前进程。 异常未捕获 信号 {'EXIT', Pid, Why}  发送给
      

      error(Exception)

    • let it crash

      在Erlang里,防御式编程是内建的

      永远不要在函数被错误参数调用时返回一个值,而是要抛出一个异常错误。要假定调用者会修复这个错误。

      抛错要快而明显,也要文明。

      立即崩溃是为了不让事情变得更糟。错误消息应当被写入永久性的错误日志,而且要包含足够多的细节,以便过后查明是哪里出了错。错误消息对程序员来说就像是来之不易的砂金,绝不能任由它们随着屏幕滚动而永远消失。

      程序员才应该能看到程序崩溃时产生的详细错误消息。程序的用户绝对不能看到这些消息。用户应当得到警告,让他们知道有错误发生这一情况,以及可以采取什么措施来弥补错误。

  • 二进制 binary

    位数都会是8的整数倍

    构造

    析构

    类型转换函数

    io 列表

    type: iolist -> [ iolist I:int when 0<= I <= 255 binary ]
     2> <<255>>.
     <<"ÿ">>
     3> <<256>>.
     <<0>>
     4> list_to_binary([256]).
     ** exception error: bad argument
         in function  list_to_binary/1
             called as list_to_binary([256])
     5> <<256,257,258>>.
     <<0,1,2>>
     6> <<"abc">>.
     <<"abc">>
     7> list_to_binary([255]).
     <<"ÿ">>
     22> X = "\777".
     X = "\777".
     [511]
    	
     32> X = 0.58.
     35> <<X/float>>.
     <<X/float>>.
     <<63,226,143,92,40,245,194,143>>
    
    

    0.58在内存中的实际数据

    • 整数截断
    • list_to_binary 只接受 io 列表

    • 实际应用 解析 IP 协议 寻找 MPEG 数据里的同步帧
  • 位串

    强调数据里的位数不是8的整数倍

  • 杂项 programming erlang 2e chapter 8