Erlang极简学习笔记<01>——启程篇

  • Erlang是一门函数式编程语言。Erlang的核心特征是容错,并发只是容错这个约束下的一个副产品

  • 对于同样的参数,函数永远要返回同样的值,这个概念称为引用透明性(referential transparency)

  • Erlang采用了actor模型,每个actor都是虚拟机中的一个独立进程

  • Erlang中只能创建出相互之间完全没有共享、只能通过消息通信的actor(进程)。每次消息交互都是显示的、可追踪的和安全的

  • Erlang不关心输入的是浮点数还是整数,算术运算符对两种类型都有效

    2 + 15.
    49 * 100.
    5 / 2.
    
  • 如果需要整除或者余数,要使用divrem

    5 div 2.
    5 rem 2.
    
  • 算术计算遵循标准优先级规则

    50 * 100 - 4999.
    
  • 以不为10的基数表示整数,需要以Base#Value这种形式输入数值(Base必须在2到36之间)

    2#101010.
    8#0677.
    16#AE.
    
  • 变量必须以大写字符开始,一个变量只能绑定一次,并且改变任何变量的值都是绝对不允许的

    One = 1.
    Two = One + One.
    
  • 变量还可以以下划线(_)开始,但是依照惯例,这种变量仅用于不想关心其值的情况

  • =操作符的行为表现其实是模式匹配(pattern matching)

    2 = 1 + 1.
    
  • 在eshell中可以使用f(Variable).函数删除一个变量,可以使用f().删除所有变量。这两个函数专门用来辅助代码实验,所以只能在shell中使用

  • 原子以小写字符开始,如果不以小写字符开头或者其中包含有除字母、数字、下划线以及@符号之外的其他符号,那么必须被放到两个单引号(')之间

    atom.
    atom@erlang.
    'Atoms can be cheated!'.
    atom = 'atom'.
    
  • 每个原子都会被引用到一个原子表中,原子表不被垃圾回收,原子表会消耗内存(32位系统4字节,64位系统8字节),系统最大原子个数1048577个

  • 不要动态创建原子,在实际开发中应确保所有原子都是手动输入的

  • 有些原子是保留字,这些原子不能使用

    after、and、andalso、band、begin、bnot、bor、bsl、bsr、bxor、case、catch、cond、div、end、fun、if、let、not、of、or、orelse、query、receive、rem、try、when和xor
    
  • 布尔操作符andor对操作符两边的参数都会去求值。如果想要一个短路操作符(只在必要时,才去求右值),可以使用andalsoorelse

    false or true.
    true xor false.
    not false.
    not (true and true).
    
  • Erlang使用=:==/=来做相等性和不等性测试

    5 =:= 5.
    1 =:= 0.
    1 =/= 0.
    5 =:= 5.0.
    
  • Erlang做比较时,会区分浮点数和整数。如果不想区分可以使用==/=

    5 == 5.0.
    5 /= 5.0.
    
  • 根据经验,你应该始终使用=:==/=,只有在明确知道确实不需要精确相等性时才换成==/=

  • 其他比较操作符:<(小于)、>(大于)、>=(大于等于)和=<(小于等于)。注意最后一个!

    1 < 2.
    1 >= 1.
    1 =< 1.
    
  • 比较操作中,数据类型之间的大小顺序是:number < atom < reference < fun < port < pid < tuple < list < bit string

  • Erlang元组书写形式:{Element1, Element2, ..., ElementN}。获取元组中元素可以使用模式匹配

    Point = {3, 4}.
    {X, Y} = Point.
    
  • Erlang列表的书写形式:[Element1, Element2, ..., ElementN],列表可以混合放入多种数据类型

  • Erlang中没有字符串数据类型。字符串就是列表

    [97, 98, 99].
    
  • ++操作符可以把列表粘合起来,--操作符可以从列表中删除元素。++--操作符都是右结合的,这意味着多个++--操作是从右向左进行的

    [1, 2, 3] ++ [4, 5].
    [1, 2, 3, 4, 5] -- [1, 2, 3].
    
    [1, 2, 3] -- [1, 2] -- [3].
    [1, 2, 3] -- [1, 2] -- [2].
    
  • 列表第一个元素称为头(head),剩余部分称为尾(tail)。可以用内建函数(BIF)获取他们

    hd([1, 2, 3, 4]).
    tl([1, 2, 3, 4]).
    
  • BIF通常是一些不能用纯Erlang实现的函数,因此会用C或者其他任何实现Erlang的语言编写。也有一些BIF本可以用Erlang实现,但是为了让这些常用的操作性更高,就用C实现了。例如:length(List)

  • 可以使用模式匹配来分离列表的头部和尾部

    [Head|Tail] = [1, 2, 3, 4].
    
  • 构建列表还可以使用|操作符,|操作符又称为cons操作符(构造器),仅凭cons操作符和值就能构建出任何列表

  • 任何列表都可以使用这个形式构建:[Term1| [Term2| [...| [TermN]]]]

  • 列表推导式(list comprehension)可以用来构建或修改列表。和其他列表操作方式相比,它们会让程序既短小又易于理解

  • 列表推导式的形式:NewList = [Expression || Pattern <- List, Condition1, Condition2, ..., ConditionN],其中Pattern <- List部分称为生成器表达式

    [2*N || N <- [1, 2, 3, 4]].
    
  • 列表推导式中还可以使用具有布尔返回值的操作来增加约束条件

    [X || X <- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], X rem 2 =:= 0].
    
  • 列表推导式还可以同时使用多个生成器表达式。下面这个表达式会执行1+3, 1+4, 2+3, 2+4这4个操作

    [X+Y || X <- [1, 2], Y <- [3, 4]]
    
  • 所以列表表达式更通用的形式应该是:NewList = [Expression || GeneratorExp1, GeneratorExp2, ..., GeneratorExpN, Condition1, Condition2, ..., ConditionN]

  • 列表表达式也可以把生成器表达式和模式匹配放一起当成过滤器来使用

    Weather = [{toronto, rain}, {montreal, storms}, {london, fog}, {paris, sun}, {boston, fog}, {vancouver, snow}].
    FoggyPlace = [X || {X, fog} <- Weather].
    
  • Erlang中的位语法会把二进制数据用<<>>括起来,并把数据分隔成多个易理解的区段,区段之间用逗号分隔。每一段都是一个二进制位序列(不一定要在字节边界上,尽管默认情况下会这样)

    Color = 16#F09A29.
    Pixel = <<Color:24>>.
    
  • 同样可以使用模式匹配从二进制数据中提取内容

    Pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>.
    <<Pix1:24, Pix2:24, Pix3:24, Pix4:24>> = Pixels.
    
    <<R:8, G:8, B:8>> = <<Pixel:24>>.
    
  • 如果只想取第一个颜色,可以使用Erlang的语法糖Rest/binaryRest/binary是一种特别的表示法,它可以将剩余的二进制数据都放到Rest变量中。所以<<Pattern, Rest/binary>>[Head|Tail]是非常相似的

    <<R:8, Rest/binary>> = Pixels.
    
  • 一个二进制区段的描述,Erlang允许有多种方式

    Value
    Value:Size
    Value/TypeSpecifierList
    Value:Size/TypeSpecifierList
    
  • 其中如果没有指定TypeSpecifierList,那么Size的单位永远是位

  • TypeSpecifierList由下面的一个或多个组成,之间用连字符(-)分隔

    • 类型:integer, float, binary, bytes, bitstring, bits, utf8, utf16, utf32

      如果不指定类型,Erlang默认使用integer类型。其中bytesbinary的缩写,bitsbitstring的缩写

    • 符号类型:signed, unsigned

      默认是unsigned,只有当类型为integer时,这个字段才有意义

    • 字节序:big, littlenative

      字节序默认是big,因为它是网络协议编码中使用的标准字节序。只有当类型为integer, utf16, utf32或者float时,字节序才有意义

    • 单位:写成unit:Integer这样的形式

      单位指的是每个区段的大小。取值范围为1~256。对于integer, floatbitstring类型来说,单位默认值是1;对于binary类型,单位默认值为8。utf系列无需定义unit

      注意: Size和单位的乘积等于要提取的区段中的位数,并且必须能被8整除。单位的大小通常用来确保字节对齐

      <<25:4/unit:8>>.
      <<25:2/unit:16>>.
      <<25:1/unit:32>>.
      

      Erlang会接受<<25:Size/unit:Unit>>的形式,并用Size乘以Unit算出这个值所需的空间,空间的大小要能被8整除

      <<X1/unsigned>> == <<-44>>.
      <<X2/signed>> = <<-44>>.
      <<X3/integer-signed-little>> = <<-44>>.
      <<N:8/unit:1>> = <<72>>.
      <<N/integer>> = <<72>>.
      <<Y:4/little-unit:8>> = <<72, 0, 0, 0>>.
      
  • Erlang提供了标准的二进制操作:bsl(按左移位),bsr(按右移位),bandborbxor以及bnot

    2#00100 = 2#00010 bsl 1.
    2#00001 = 2#00010 bsr 1.
    2#10101 = 2#10001 bor 2#00101.
    
  • 二进制字符串在语言中的实现方式,和用列表实现的字符串使用的方式完全一样,只是在空间使用上更加高效

  • 普通字符串与链表类似,二进制字符串更像C语言中的数组

  • 二进制字符串的形式:<<"This is a binary string!">>。其缺点是,它的模式匹配和操作方法没有列表这么简单。因此,通常当所存储的文本无需频繁操作或空间效率是个实际问题时,才会使用二进制字符串

  • 二进制推导式(binary comprehension)之于位语法就等同于列表推导式之于列表:在处理二进制数据时,可以让代码短小精悍

    << <<X>> || <<X>> <= <<1, 2, 3, 4, 5>>, X rem 2 == 0 >>.
    
  • 语法层面的变化就是:标准列表推导式中的<-变成了<=(用于二进制生成器),使用的是二进制数据(<<>>),而不是列表数据([])

  • 相比之前的代码,这里有个更强大的用法

    Pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>.
    RGB = [ {R, G, B} || <<R:8, G:8, B:8>> <= Pixels ].
    << <<R:8, G:8, B:8>> || {R, G, B} <- RGB >>.
    
  • 如果生成器返回的是二进制数,那么就必须要对结果二进制数中的元素给出明确的二进制类型定义

    << <<Bin/binary>> || Bin <- [<<3, 7, 5, 4, 7>>] >>.
    
  • 默认情况下Erlang会认为放入二进制数中以及二进制数中提取的值都是整数(8位无符号)

  • 还可以在二进制推导式中使用二进制生成器

    << <<(X+1)/integer>> || <<X>> <= <<3, 7, 5, 4, 7>> >>.
    

原文地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容