1
1
defmodule Record do
2
2
@ moduledoc """
3
- Module to work with, define and import records.
3
+ Module to work with, define, and import records.
4
4
5
5
Records are simply tuples where the first element is an atom:
6
6
@@ -17,15 +17,14 @@ defmodule Record do
17
17
1. to work with short, internal data
18
18
2. to interface with Erlang records
19
19
20
- The macros `defrecord/3` and `defrecordp/3` can be used to create
21
- records while `extract/2` can be used to extract records from Erlang
22
- files.
20
+ The macros `defrecord/3` and `defrecordp/3` can be used to create records
21
+ while `extract/2` and `extract_all/1` can be used to extract records from
22
+ Erlang files.
23
23
24
24
## Types
25
25
26
- Types can be defined for tuples with the `record/2` macro (only available
27
- in typespecs). Like with the generated record macros it will expand to
28
- a tuple.
26
+ Types can be defined for tuples with the `record/2` macro (only available in
27
+ typespecs). This macro will expand to a tuple as seen in the example below:
29
28
30
29
defmodule MyModule do
31
30
require Record
@@ -34,14 +33,34 @@ defmodule Record do
34
33
@type user :: record(:user, name: String.t, age: integer)
35
34
# expands to: "@type user :: {:user, String.t, integer}"
36
35
end
36
+
37
37
"""
38
38
39
39
@ doc """
40
40
Extracts record information from an Erlang file.
41
41
42
42
Returns a quoted expression containing the fields as a list
43
- of tuples. It expects the record name to be an atom and the
44
- library path to be a string at expansion time.
43
+ of tuples.
44
+
45
+ `name`, which is the name of the extracted record, is expected to be an atom
46
+ *at compile time*.
47
+
48
+ ## Options
49
+
50
+ This function accepts the following options, which are exclusive to each other
51
+ (i.e., only one of them can be used in the same call):
52
+
53
+ * `:from` - (binary representing a path to a file) path to the Erlang file
54
+ that contains the record definition to extract; with this option, this
55
+ function uses the same path lookup used by the `-include` attribute used in
56
+ Erlang modules.
57
+ * `:from_lib` - (binary representing a path to a file) path to the Erlang
58
+ file that contains the record definition to extract; with this option,
59
+ this function uses the same path lookup used by the `-include_lib`
60
+ attribute used in Erlang modules.
61
+
62
+ These options are expected to be literals (including the binary values) at
63
+ compile time.
45
64
46
65
## Examples
47
66
@@ -59,18 +78,33 @@ defmodule Record do
59
78
@ doc """
60
79
Extracts all records information from an Erlang file.
61
80
62
- Returns a keyword list containing extracted record names as keys, and
63
- lists of tuples describing the fields as values. It expects a named
64
- argument :from or :from_lib, which correspond to *include* or
65
- *include_lib* attribute from Erlang modules, respectively.
81
+ Returns a keyword list of `{record_name, fields}` tuples where `record_name`
82
+ is the name of an extracted record and `fields` is a list of `{field, value}`
83
+ tuples representing the fields for that record.
84
+
85
+ ## Options
86
+
87
+ This function accepts the following options, which are exclusive to each other
88
+ (i.e., only one of them can be used in the same call):
66
89
90
+ * `:from` - (binary representing a path to a file) path to the Erlang file
91
+ that contains the record definitions to extract; with this option, this
92
+ function uses the same path lookup used by the `-include` attribute used in
93
+ Erlang modules.
94
+ * `:from_lib` - (binary representing a path to a file) path to the Erlang
95
+ file that contains the record definitions to extract; with this option,
96
+ this function uses the same path lookup used by the `-include_lib`
97
+ attribute used in Erlang modules.
98
+
99
+ These options are expected to be literals (including the binary values) at
100
+ compile time.
67
101
"""
68
102
def extract_all ( opts ) when is_list ( opts ) do
69
103
Record.Extractor . extract_all ( opts )
70
104
end
71
105
72
106
@ doc """
73
- Checks if the given `data` is a record of `kind`.
107
+ Checks if the given `data` is a record of kind `kind`.
74
108
75
109
This is implemented as a macro so it can be used in guard clauses.
76
110
@@ -110,6 +144,9 @@ defmodule Record do
110
144
iex> tuple = {}
111
145
iex> Record.is_record(tuple)
112
146
false
147
+ iex> other_term = "not a record"
148
+ iex> Record.is_record(other_term)
149
+ false
113
150
114
151
"""
115
152
defmacro is_record ( data ) do
@@ -128,11 +165,26 @@ defmodule Record do
128
165
end
129
166
130
167
@ doc """
131
- Defines a set of macros to create and access a record.
168
+ Defines a set of macros to create, access, and pattern match
169
+ on a record.
170
+
171
+ The name of the generated macros will be `name` (which has to be an
172
+ atom). `tag` is also an atom and is used as the "tag" for the record (i.e.,
173
+ the first element of the record tuple); by default (if `nil`), it's the same
174
+ as `name`. `kv` is a keyword list of `name: default_value` fields for the
175
+ new record.
176
+
177
+ The following macros are generated:
132
178
133
- The macros are going to have `name`, a tag (which defaults)
134
- to the name if none is given, and a set of fields given by
135
- `kv`.
179
+ * `name/0` to create a new record with default values for all fields
180
+ * `name/1` to create a new record with the given fields and values or to
181
+ convert the given record to a keyword list
182
+ * `name/2` to update an existing record with the given fields and values
183
+ or to access a given field in a given record
184
+
185
+ All these macros are public macros (as defined by `defmacro`).
186
+
187
+ See the "Examples" section for examples on how to use these macros.
136
188
137
189
## Examples
138
190
@@ -142,7 +194,7 @@ defmodule Record do
142
194
end
143
195
144
196
In the example above, a set of macros named `user` but with different
145
- arities will be defined to manipulate the underlying record:
197
+ arities will be defined to manipulate the underlying record.
146
198
147
199
# To create records
148
200
record = user() #=> {:user, "meg", 25}
@@ -165,8 +217,8 @@ defmodule Record do
165
217
user(name: name) = record
166
218
name #=> "meg"
167
219
168
- By default, Elixir uses the record name as the first element of
169
- the tuple (the tag). But it can be changed to something else :
220
+ By default, Elixir uses the record name as the first element of the tuple (the
221
+ " tag" ). However, a different tag can be specified when defining a record :
170
222
171
223
defmodule User do
172
224
require Record
@@ -176,11 +228,11 @@ defmodule Record do
176
228
require User
177
229
User.user() #=> {User, nil}
178
230
179
- ## Defining extracted records with anonymous functions
231
+ ## Defining extracted records with anonymous functions in the values
180
232
181
- If a record defines an anonymous function, an `ArgumentError`
182
- will occur if you attempt to create a record with it.
183
- This can occur unintentionally when defining a record after extracting
233
+ If a record defines an anonymous function in the default values,
234
+ an `ArgumentError` will occur if you attempt to create a record with it.
235
+ This can happen unintentionally when defining a record after extracting
184
236
it from an Erlang library that uses anonymous functions for defaults.
185
237
186
238
Record.defrecord :my_rec, Record.extract(...)
@@ -195,6 +247,7 @@ defmodule Record do
195
247
Record.defrecord :my_rec, Record.extract(...) |> Keyword.merge(fun_field: &__MODULE__.foo/2)
196
248
def foo(bar, baz), do: IO.inspect({bar, baz})
197
249
end
250
+
198
251
"""
199
252
defmacro defrecord ( name , tag \\ nil , kv ) do
200
253
quote bind_quoted: [ name: name , tag: tag , kv: kv ] do
0 commit comments