Record
Module to work with, define and import records.
Records are simply tuples where the first element is an atom:
iex> Record.is_record {User, "john", 27} true
This module provides conveniences for working with records at compilation time, where compile-time field names are used to manipulate the tuples, providing fast operations on top of the tuples’ compact structure.
In Elixir, records are used mostly in two situations:
- to work with short, internal data
- to interface with Erlang records
The macros defrecord/3
and defrecordp/3
can be used to create records while extract/2
can be used to extract records from Erlang files.
Types
Types can be defined for tuples with the record/2
macro (only available in typespecs). Like with the generated record macros it will expand to a tuple.
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
Summary
Functions
- defrecord(name, tag \\ nil, kv)
-
Defines a set of macros to create and access a record
- defrecordp(name, tag \\ nil, kv)
-
Same as
defrecord/3
but generates private macros - extract(name, opts)
-
Extracts record information from an Erlang file
- extract_all(opts)
-
Extracts all records information from an Erlang file
- is_record(data)
-
Checks if the given
data
is a record - is_record(data, kind)
-
Checks if the given
data
is a record ofkind
Functions
defrecord(name, tag \\ nil, kv) (macro)
Defines a set of macros to create and access a record.
The macros are going to have name
, a tag (which defaults) to the name if none is given, and a set of fields given by kv
.
Examples
defmodule User do require Record Record.defrecord :user, [name: "meg", age: "25"] end
In the example above, a set of macros named user
but with different arities will be defined to manipulate the underlying record:
# 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} # Convert a record to a keyword list user(record) #=> [name: "meg", age: 26]
The generated macros can also be used in order to pattern match on records and to bind variables during the match:
record = user() #=> {:user, "meg", 25} user(name: name) = record name #=> "meg"
By default, Elixir uses the record name as the first element of the tuple (the tag). But it can be changed to something else:
defmodule User do require Record Record.defrecord :user, User, name: nil end require User User.user() #=> {User, nil}
Defining extracted records with anonymous functions
If a record defines an anonymous function, an ArgumentError
will occur if you attempt to create a record with it. This can occur unintentionally when defining a record after extracting it from an Erlang library that uses anonymous functions for defaults.
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>.
To work around this error, redefine the field with your own &M.f/a function, like so:
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) (macro)
Same as defrecord/3
but generates private macros.
extract(name, opts)
Extracts record information from an Erlang file.
Returns a quoted expression containing the fields as a list of tuples. It expects the record name to be an atom and the library path to be a string at expansion time.
Examples
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]
extract_all(opts)
Extracts all records information from an Erlang file.
Returns a keyword list containing extracted record names as keys, and lists of tuples describing the fields as values. It expects a named argument :from or :from_lib, which correspond to include or include_lib attribute from Erlang modules, respectively.
is_record(data) (macro)
Checks if the given data
is a record.
This is implemented as a macro so it can be used in guard clauses.
Examples
iex> record = {User, "john", 27} iex> Record.is_record(record) true iex> tuple = {} iex> Record.is_record(tuple) false
is_record(data, kind) (macro)
Checks if the given data
is a record of kind
.
This is implemented as a macro so it can be used in guard clauses.
Examples
iex> record = {User, "john", 27} iex> Record.is_record(record, User) true
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.3.4/Record.html