檢視原始碼 記錄 (Elixir v1.16.2)

與記錄共用、定義和匯入的模組。

記錄僅為第一個元素為原子的元組

iex> Record.is_record({User, "john", 27})
true

此模組提供在編譯時使用記錄的便利性,其中編譯時欄位名稱用於處理元組,提供元組緊湊結構上的快速運算。

在 Elixir 中,記錄主要用於兩種情況

  1. 處理簡短的內部資料
  2. 與 Erlang 記錄介面

巨集 defrecord/3defrecordp/3 可用於建立記錄,而 extract/2extract_all/1 可用於從 Erlang 檔案中萃取記錄。

類型

可以使用 record/2 巨集為元組定義類型(僅在類型規格中可用)。此巨集會擴充為元組,如下面的範例所示

defmodule MyModule do
  require Record
  Record.defrecord(:user, name: "john", age: 25)

  @type user :: record(:user, name: String.t(), age: integer)
  # expands to: "@type user :: {:user, String.t(), integer}"
end

反射

如果模組中有任何記錄,可透過讀取 @__records__ 模組屬性來擷取所有記錄的清單。它會傳回一個清單,其中包含記錄種類、名稱、標籤和欄位。此屬性僅在模組定義中可用。

摘要

防護

檢查給定的 data 是否為記錄。

檢查給定的 data 是否為種類 kind 的記錄。

函數

定義一組巨集,用於建立、存取和模式比對記錄。

defrecord/3 相同,但會產生私有巨集。

從 Erlang 檔案中萃取記錄資訊。

從 Erlang 檔案中萃取所有記錄資訊。

守衛

檢查給定的 data 是否為記錄。

這是以巨集實作的,因此可以在守衛子句中使用。

範例

Record.is_record({User, "john", 27})
#=> true

Record.is_record({})
#=> false
連結到此巨集

is_record(data, kind)

檢視原始碼 (巨集)

檢查給定的 data 是否為種類 kind 的記錄。

這是以巨集實作的,因此可以在守衛子句中使用。

範例

iex> record = {User, "john", 27}
iex> Record.is_record(record, User)
true

函數

連結到此巨集

defrecord(name, tag \\ nil, kv)

檢視原始碼 (巨集)

定義一組巨集,用於建立、存取和模式比對記錄。

所產生巨集的名稱將會是 name(必須是原子)。tag 也是原子,用作記錄的「標籤」(亦即記錄元組的第一個元素);預設(如果為 nil)則與 name 相同。kv 是新記錄的 name: default_value 欄位的關鍵字清單。

會產生下列巨集

  • name/0 用所有欄位的預設值建立新的記錄
  • name/1 用給定的欄位和值建立新的記錄,取得記錄中給定欄位的零為基準索引,或將給定的記錄轉換為關鍵字清單
  • name/2 用給定的欄位和值更新現有的記錄,或存取給定記錄中的給定欄位

所有這些巨集都是公開巨集(由 defmacro 定義)。

有關如何使用這些巨集的範例,請參閱「範例」區段。

範例

defmodule User do
  require Record
  Record.defrecord(:user, name: "meg", age: "25")
end

在上面的範例中,會定義一組名為 user 但具有不同元數的巨集,用於操作基礎記錄。

# Import the module to make the user macros locally available
import User

# To create records
record = user()        #=> {:user, "meg", 25}
record = user(age: 26) #=> {:user, "meg", 26}

# To get a field from the record
user(record, :name) #=> "meg"

# To update the record
user(record, age: 26) #=> {:user, "meg", 26}

# To get the zero-based index of the field in record tuple
# (index 0 is occupied by the record "tag")
user(:name) #=> 1

# Convert a record to a keyword list
user(record) #=> [name: "meg", age: 26]

也可以使用產生的巨集來比對記錄的模式,並在比對期間繫結變數

record = user() #=> {:user, "meg", 25}

user(name: name) = record
name #=> "meg"

預設情況下,Elixir 會使用記錄名稱作為元組的第一個元素(「標籤」)。不過,在定義記錄時可以指定不同的標籤,如下列範例所示,其中我們使用 Customer 作為 defrecord/3 的第二個引數

defmodule User do
  require Record
  Record.defrecord(:user, Customer, name: nil)
end

require User
User.user() #=> {Customer, nil}

在值中使用匿名函數定義萃取的記錄

如果記錄在預設值中定義匿名函數,就會產生 ArgumentError。在從使用匿名函數作為預設值的 Erlang 函式庫萃取記錄後定義記錄時,可能會不小心發生這種情況。

Record.defrecord(:my_rec, Record.extract(...))
** (ArgumentError) invalid value for record field fun_field,
    cannot escape #Function<12.90072148/2 in :erl_eval.expr/5>.

若要解決這個錯誤,請使用您自己的 &M.f/a 函數重新定義欄位,如下所示

defmodule MyRec do
  require Record
  Record.defrecord(:my_rec, Record.extract(...) |> Keyword.merge(fun_field: &__MODULE__.foo/2))
  def foo(bar, baz), do: IO.inspect({bar, baz})
end
連結到此巨集

defrecordp(name, tag \\ nil, kv)

檢視原始碼 (巨集)

defrecord/3 相同,但會產生私有巨集。

@spec extract(
  name :: atom(),
  keyword()
) :: keyword()

從 Erlang 檔案中萃取記錄資訊。

傳回包含欄位(以元組清單表示)的引述表達式。

name,也就是萃取記錄的名稱,預期在編譯時會是原子。

選項

這個函數需要下列選項之一,這些選項彼此互斥(亦即,在同一個呼叫中只能使用其中一個選項)

  • :from - (表示檔案路徑的二進位)包含要萃取的記錄定義的 Erlang 檔案路徑;使用這個選項時,這個函數會使用與 Erlang 模組中使用的 -include 屬性相同的路徑查詢。

  • :from_lib - (表示檔案路徑的二進位)包含要萃取的記錄定義的 Erlang 檔案路徑;使用這個選項時,這個函數會使用與 Erlang 模組中使用的 -include_lib 屬性相同的路徑查詢。

它另外接受下列非互斥的選用選項

  • :includes - (以二進位表示的目錄清單)如果要萃取的記錄依賴於相對包含,這個選項允許開發人員指定那些相對包含存在的目錄。

  • :macros - (巨集名稱和值的關鍵字清單)如果要萃取的記錄依賴於巨集的值,這個選項允許設定那些巨集的值。

預期這些選項在編譯時會是文字(包括二進位值)。

範例

iex> Record.extract(:file_info, from_lib: "kernel/include/file.hrl")
[
  size: :undefined,
  type: :undefined,
  access: :undefined,
  atime: :undefined,
  mtime: :undefined,
  ctime: :undefined,
  mode: :undefined,
  links: :undefined,
  major_device: :undefined,
  minor_device: :undefined,
  inode: :undefined,
  uid: :undefined,
  gid: :undefined
]
@spec extract_all(keyword()) :: [{name :: atom(), keyword()}]

從 Erlang 檔案中萃取所有記錄資訊。

傳回關鍵字清單,其中包含 {record_name, fields} 元組,其中 record_name 是萃取記錄的名稱,而 fields{field, value} 元組清單,代表該記錄的欄位。

選項

接受與 Record.extract/2 列出的相同選項。