Skip to content

Commit 6c2744d

Browse files
committed
Add index reflection to private records
Example: defrecordp :user, [:name, age] user(:age) #=> 2
1 parent f671e12 commit 6c2744d

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

lib/elixir/lib/record.ex

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,24 @@ defmodule Record do
453453
Module.put_attribute(module, :record_optimizable, functions)
454454
end
455455

456+
@doc false
457+
# Implements the access macro used by records.
458+
# It returns the index of the given field.
459+
def access(atom, fields, arg, _caller) when is_atom(arg) do
460+
if index = find_index(fields, arg, 0) do
461+
index + 1
462+
else
463+
raise ArgumentError, message: "record #{inspect atom} does not have the key: #{inspect arg}"
464+
end
465+
end
466+
456467
# Implements the access macro used by records.
457468
# It returns a quoted expression that defines
458469
# a record or a match in case the record is
459470
# inside a match.
460-
@doc false
461471
def access(atom, fields, keyword, caller) do
462472
unless is_keyword(keyword) do
463-
raise ArgumentError, message: "expected contents inside brackets to be a keyword list, got: #{inspect keyword}"
473+
raise ArgumentError, message: "expected contents inside brackets to be a keyword list or an atom, got: #{inspect keyword}"
464474
end
465475

466476
in_match = caller.in_match?

lib/elixir/test/elixir/kernel/errors_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ defmodule Kernel.ErrorsTest do
491491
end
492492

493493
test :invalid_access_protocol_not_keywords do
494-
assert_raise ArgumentError, "expected contents inside brackets to be a keyword list, got: [0]", fn ->
494+
assert_raise ArgumentError, "expected contents inside brackets to be a keyword list or an atom, got: [0]", fn ->
495495
defmodule ErrorsTest do
496496
def sample(Kernel.ErrorsTest.Config[0]), do: true
497497
end

lib/elixir/test/elixir/record/private_test.exs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ defmodule Record.PrivateTest do
4545
_user(user, [:age, :name])
4646
end
4747

48+
def name_ix() do
49+
_user(:name)
50+
end
51+
52+
def age_ix() do
53+
_user(:age)
54+
end
55+
4856
def my_new() do
4957
_my_user()
5058
end
@@ -77,6 +85,14 @@ defmodule Record.PrivateTest do
7785
_my_user(user, [:age, :name])
7886
end
7987

88+
def my_name_ix() do
89+
_my_user(:name)
90+
end
91+
92+
def my_age_ix() do
93+
_my_user(:age)
94+
end
95+
8096
def file_info() do
8197
_file_info()
8298
end
@@ -128,6 +144,13 @@ defmodule Record.PrivateTest do
128144
assert elem(record, 0) == Macros
129145
end
130146

147+
test "defrecordp access index" do
148+
assert Macros.name_ix == 1
149+
assert Macros.age_ix == 2
150+
assert Macros.my_name_ix == 1
151+
assert Macros.my_age_ix == 2
152+
end
153+
131154
test "defrecordp with dynamic arguments" do
132155
assert [:_file_info|_] = Macros.file_info() |> tuple_to_list
133156
assert { :_dynamic, nil } = Macros.dynamic()

0 commit comments

Comments
 (0)