[elixir]elixir基础

388 阅读5分钟

Elixir类型简介

Elixir的内置类型包括:

  1. 值类型(5个)

  2. 任意大小的整数

  3. 浮点数

  4. atom

  5. range

  6. 正则表达式

  7. 系统类型(2个)

  8. PID和port

  9. 引用(reference)

  10. 集合类型(4个)

  11. tuple

  12. list

  13. map

  14. binary

值类型

整数

整数常量可以写成十进制,如:123。十六进制,如:0xcafe。八进制,如:0o765。二进制,如:0b1010。Elixir中,整数的内部存储会随着表示的值的增加而扩大,因此,Elixir中的整数可以表示任意大小。整数常量可以包含下划线,如:10_000_000

浮点数

小数点前后至少要包含一位数字,如:0.123, 1.23。末尾可以添加可选的科学表示,如:0.12e1

Atom

Atom是常量,表示某种名称。以冒号开始,后跟UTF-8的字母、数字、下划线或者@符号,末尾可以添加问号或者叹号,如::fred​ ​:is_binary?​ ​:var@2​ ​:<>​ ​:===​ ​:"func/3"​ ​ ​:"long john silver"​ ​:эликсир​ ​:mötley_crüe

Atom也可以在冒号后面跟双引号,引号内可以添加任何字符来表示Atom。Atom的名称就是它的值,因此,只要2个Atom的名称一样,它们总是相同的。

Range

Range(范围)表示为start..end。

正则表达式

Elixir中的正则表达式字面量为~r{regexp}或者~r{regexp}opts。这里使用{}作为分隔符。实际上,可以使用任何非字母、数字的字符,如:~r/regexp/,使用斜线做分隔符。但是,注意,这种场景需要将正则表达式中的斜线做转义处理。更多的是使用{}作为分隔符。

Elixir中的正则表达式功能由PCRE提供。

  1. opt的可选值包括:
  2. f : 强制对多行字符串从第一行开始匹配
  3. i : 忽略大小写
  4. m : 针对多行字符串,^和$匹配每行的行头和行尾。\A和\z匹配多行字符串的开头和末尾
  5. s : 允许.(dot)匹配任何换行符
  6. U : 通常*和+会尽量匹配更多(greedy),使用这个opt,会尽量少的匹配(ungreedy)。
  7. u : 启用unicode特定的模式,如:\p
  8. x : 启用扩展模式,忽略空白和注释(# 到行尾)

Elixir中采用Regex module提供的方法来操作正则表达式,如Regex module中的run, scan, split, replace方法。

系统类型

该分类下的类型反应的是底层Erlang VM的资源。

PID和port

PID代表本地或者远程process的引用。当前process的PID可以通过调用self获得。port代表当前应用外的资源的引用。通常我们在创建(spawn)一个新的process的时候,就会创建一个新的PID。

引用(reference)

函数make_ref会创建全局唯一的引用(reference)。

集合类型

Elixir中的集合类型可以包含任何类型,包括其他的集合类型。

Tuple

Tuple表示有序的值列表,如:{1, 2}, {:ok, 42, "next"}。通常,Elixir中的Tuple包含两个到四个元素,多余四个最好改为map或者struct。Tuple的常用场景就是函数调用的返回值,首个元素为:ok表示调用成功,:error表示调用失败。

注意,Elixir中Tuple类比其他语言中的数组。

List

Elixir中列表是个链表结构。列表的递归定义:列表有head和tail构成,head包含值,tail本身也是个列表。由于列表是链表结构,导致遍历列表效率很高,我们可以很快的访问列表的头元素或者尾元素。但是随机访问将是性能昂贵的操作。

Elixir提供了一些特定于列表的操作符号:

  1. ++ 用于拼接列表,如:[1,2,3] ++ [4,5,6] 返回 [1,2,3,4,5,6]
  2. -- 用于求差,如:[1,2,3,4] -- [2,3] 返回 [1,4]
  3. in 判断是否包含元素,如:1 in [1,2] 返回 true

由于经常定义关键字列表,Elixir提供了简易语法:[name: "Dave", city: "Dallas"]。Elixir会把上述表达转换成[{:name, "Dave"}, {:city, "Dallas"}]

如果函数调用的最后一个参数是关键字列表,那么我们可以省去外层括号,如:DB.save record, [{:use_transaction, true}, {:logging, "HIGH"}] 可以简写为 DB.save record, {:use_transaction, true}, {:logging, "HIGH"}

Map

Map的定义格式为 %{key => value, key=>value}。尽管Map中的key通常是相同类型,但是Elixir中并不强制。

如果Map中的key是Atom,那么我们可以采用类似关键字类表一样的简写方式,如:%{red: 0xff000, green: 0x00ff00}

Binary

二进制将数据表示为bit或者byte的序列。二进制常量用<<和>>包括,如:<<1,2>>默认将数字1和2表示为byte序列。byte_size <<1,2>>返回2,表示占2个字节。同样,可以通过::size()来自定数字占用的bit数,如:<<3 :: size(2), 5 :: size(4), 1 :: size(2)>>表示数字3占用2个bit,数字5占用4个bit,数字1占用2个bit,对应的二进制表示为11010101。

日期和时间

Date类型

Date类型包含了年、月、日。可以通过Date.new函数来创建,如:Data.new(2018, 12, 25),返回{:ok, ~D[2018-12-25]}。也可以通过字面量方式(sigil)创建,如:~D[2018-12-25]会创建一个Date类型的字面量日期值。

常用的Date函数:

  1. Date.day_of_week获取当前日期是当前周的第几天(周一为第一天)。
  2. Date.range 获取两个日期之间的间隔DateRange(包括起始和截止日期)。
  3. in 判断日期是否在某个DateRange内。

Time类型

Time类型包括了小时,分,秒以及秒的小数部分(fraction)。秒的小数部分包括微秒(microseconds以及重要数字的个数 the number of significant digits)。可以通过Time.new来创建时间类型,如:Time.new(12, 34,56)返回~T[12:34:56]。也可以通过字面量的方式(sigil)创建,如:~T[12:34:56.78]。

注意,秒的小数分关键数字的个数不同会导致2个时间的不同,如:T[12:34:56.0]与T[12:34:56.00]是不同的2个时间。

可以通过Time.add为Time类型值添加时间,如:

t1 = ~T[12:34:56]; Time.add(t1, 3600) #默认添加值的单位是秒。返回 ~T[13:34:56.000000]

也可以指定添加值的类型,如:Time.add(t1, 3600, :millisecond),返回 ~T[12:34:59.600000]。

Elixir中包括2种日期时间类型:DateTime和NativeDateTime。native版本只包括日期和时间,DateTime不仅包含日期和时间,还可以关联时区。~N[..]用来创建native版本的日期时间字面量。

标识符命名

必须以字符或下划线开始,后跟字符、数字或下划线。这里的字符指任何UTF-8字符。数字指UTF-8十进制数字。标识符末尾可以添加问号或者感叹号。以下为有效标识符命名:name josé _age まつもと _42 адрес!以下为无效的标识符命名:name• a±2 42

Module,record,protocal和behavior的命名以大写字符开头,采用驼峰式。其他的标识符命名则采用小写字符或者下划线开头,并用下划线分隔单词。

源码文件中,通常采用两字符的缩进表示嵌套。Elixir用空格而不是制表符(tab)表示缩进。通常在编写完Elixir程序后,使用mix format来格式化源代码。

Boolean

Elixir中有3个与布尔相关的值:true、false和nil。在布尔环境中,nil表示false。这3个值都是Atom。所以,true其实就是:true。大部分场景中,任何值只要不是false或者nil就会认为是true,这种情况被称作truthy。

操作符

Elixir提供丰富的操作符

  1. a === b 严格相等,1 === 1.0 返回false
  2. a !== b 严格不等,1 !== 1.0 返回true
  3. a == b 值等,1 == 1.0 返回true
  4. a != b 值不等, 1 != 1.0 返回false
  5. a > b 大于
  6. a >= b 大于等于
  7. a < b 小于
  8. a <= b 小于等于

布尔操作符

以下布尔操作符要求第一个参数必须为true或者false,否则编译器报错。

a and b 如果a为false,返回false,不然返回b(b可以不是true或者false)

a or b 如果a为true,返回true,不然返回b

not a 如果a为true,返回false,不然返回true

宽松的布尔操作符

a || b 如果a是truthy,返回a,不然返回b

a && b 如果a是truthy,返回b,不然返回a

!a a是truthy,返回false,否则返回true

数学操作符

+,-,*,/,div,rem 整数相除会返回浮点类型的结果,如 3/2 返回1.5。若要返回整数结果,需要使用div,如:div(3,2)返回1。rem表示求余运算,如rem(11,3)返回2。

Join操作符

binary1 <> binary2 合并2个二进制,如:<<1,2>> <> <<3,4>> 返回<<1,2,3,4>>

list1 ++ list2 合并2个list,如:[1,2] ++ [3,4] 返回 [1,2,3,4]

list1 -- list2 将list2从list1中删掉,如:[1,2,3] -- [1,2] 返回[3]

in操作符

a in enumerable 判断a是否为可遍历结构(list,map,range)中的成员 。

Content mainly excerpted from 「Programming elixir >= 1.6」 by Dave Thomas