Skip to content

Commit 707b810

Browse files
author
José Valim
committed
Merge pull request #2517 from ericmj/record-fields
Add field retrieval of records via `record(record())`
2 parents e51cfc1 + 32738a9 commit 707b810

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

lib/elixir/lib/record.ex

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,9 @@ defmodule Record do
192192
Keyword.keyword?(args) ->
193193
create(atom, fields, args, caller)
194194
true ->
195-
msg = "expected arguments to be a compile time atom or keywords, got: #{Macro.to_string args}"
196-
raise ArgumentError, msg
195+
quote bind_quoted: [atom: atom, fields: fields, args: args] do
196+
Record.__keyword__(atom, fields, args)
197+
end
197198
end
198199
end
199200

@@ -281,4 +282,21 @@ defmodule Record do
281282
defp find_index([{k, _}|_], k, i), do: i + 2
282283
defp find_index([{_, _}|t], k, i), do: find_index(t, k, i + 1)
283284
defp find_index([], _k, _i), do: nil
285+
286+
# Returns a keyword list of the record
287+
@doc false
288+
def __keyword__(atom, fields, record) do
289+
if record?(record, atom) do
290+
[_tag|values] = Tuple.to_list(record)
291+
join_keyword(fields, values, [])
292+
else
293+
msg = "expected argument to be a literal atom, literal keyword or a #{atom}() record, got runtime: #{inspect record}"
294+
raise ArgumentError, msg
295+
end
296+
end
297+
298+
defp join_keyword([{field, _default}|fields], [value|values], acc),
299+
do: join_keyword(fields, values, [{field, value}| acc])
300+
defp join_keyword([], [], acc),
301+
do: :lists.reverse(acc)
284302
end

lib/elixir/test/elixir/record_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ defmodule RecordTest do
6767

6868
user(name: name) = record
6969
assert name == "Eric"
70+
71+
assert user(:name) == 1
7072
end
7173

7274
test "records with no tag" do
@@ -76,6 +78,15 @@ defmodule RecordTest do
7678
test "records with dynamic arguments" do
7779
record = file_info()
7880
assert file_info(record, :size) == :undefined
81+
82+
record = user()
83+
assert user(record) == [name: "José", age: 25]
84+
85+
msg = "expected argument to be a literal atom, literal keyword or a file_info() record, " <>
86+
"got runtime: {RecordTest, \"José\", 25}"
87+
assert_raise ArgumentError, msg, fn ->
88+
file_info(record)
89+
end
7990
end
8091

8192
test "records visibility" do

0 commit comments

Comments
 (0)