官方教程:http://elixir-lang.org/getting_started/4.html

Elixir version 0.12.5 请查看最新官方文档

Records

Records 类似于结构体,我们可以定义自己的数据类型,比如定义FileInfo record,存储文件信息:

elixirdefrecord FileInfo, atime: nil, accesses: 0

这行代码会定义一个名为FileInfo的模块,其中包含一个new 函数,使用new函数可以返回一个新的record实例:

elixiriex> file_info = FileInfo.new(atime: { 2010, 4, 17 }, accesses: 42)
iex> file_info.atime
{2010, 4, 17}
iex> file_info.atime({ 2012, 10, 13 }) #=> Returns a new FileInfo
FileInfo[atime: {2012, 10, 13}, accesses: 42]
iex> file_info.atime
{2010, 4, 17}

注意,当改变fiel_info的atime字段的时候,Elixir会创建新的record到并关联到file_info变量,因为在Elixir里变量是不可变的,所以更新record时,不是在原来的Record实例做更新,而是返回了一个新创建的Record实例

在Elixir里,record的本质是元组(tuple),且元组的第一个元素是record的名字,可以使用inspect查看原始的值

elixirinspect FileInfo.new, raw: true
#=> "{ FileInfo, nil, 0 }"

除了对Record属性定义reader和writer方法,Elixir还对属性定义了update_#{attribute} 函数,此函数接受一个匿名函数,这个匿名函数的参数是当前值,另外必须返回一个新的值,例如,下面的例子,对file_infoaccesser属性加1

elixirfile_info = FileInfo.new(accesses: 10)
file_info = file_info.update_accesses(fn(x) -> x + 1 end)
file_info.accesses #=> 11

模式匹配

模式匹配也可以用在Record,比如,获取FileInfo是否可以访问的信息,可以用模式匹配这样实现:

elixirdefmodule FileAccess do
  def was_accessed?(FileInfo[accesses: 0]), do: false
  def was_accessed?(FileInfo[]),            do: true
end

上面的例子中,第一个函数表示当accesses为0时匹配,并返回false,第二个匹配条件会匹配任何FileInfo
当然也可以一行代码实现上面的功能:

elixirdef was_accessed?(FileInfo[accesses: accesses]), do: accesses > 0

也可以用模式匹配的语法创建新的Record:

elixirfile_info = FileInfo[accesses: 0]

当使用中括号语法进行模式匹配时,Elixir会在编译时将Record展开为元组,也就是说下面的例子中:

elixirdef was_accessed?(FileInfo[accesses: 0]), do: false

相当于对元组进行模式匹配:

elixirdef was_accessed?({ FileInfo, _, 0 }), do: false

doc:
* http://elixir-lang.org/docs/master/Kernel.html#defrecord/3


lidashuang
6.7k 声望165 粉丝

$ Ruby/Elixir/Golang