# Struct attribute name from variable

**URL:** <https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503>\
**Category:** Help & Support\
**Created:** [July 12, 2021, 7:50pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503 "2021-07-12T19:50:25Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![szabgab](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/szabgab/32/1278_2.png) [@szabgab](https://forum.crystal-lang.org/u/szabgab)\
**Post date:** [July 12, 2021, 7:50pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/1 "2021-07-12T19:50:25Z")

</div>

The last line, `prs.field` (obviously) does not work. Can I somehow make call a method where the name of the method comes from a variable?

```auto
struct Person
  getter name : String
  getter email : String

  def initialize(@name, @email)
  end
end

prs = Person.new("Foo Bar", "foo@bar.com")
p! prs
p! prs.name
p! prs.email

["name", "email"].each {|field|
  #puts field
  prs.field
}

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [July 12, 2021, 8:01pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/2 "2021-07-12T20:01:11Z")

</div>

No, Crystal doesn’t have dynamic method invocation. Your best best would be doing something like:

```auto
case field
when "name" then prs.name
when "email" then prs.email
end

```

or something along those lines. However I’d argue theres probably a better way…

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [July 12, 2021, 8:04pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/3 "2021-07-12T20:04:49Z")

</div>

At runtime this is not possible. But it would work with a compile time variable in a macro:

```auto
{% for field in ["name", "email"] %}
  prs.{{ field.id }}
{% end %}

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [July 12, 2021, 8:06pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/4 "2021-07-12T20:06:10Z")

</div>

Combining the two, you could use a macro that iterates over the ivars of a type to construct the case. This ofc only would work in the context of a method and assuming that you never need to do like `prs.some_obj.some_value`.

---

<div class="post-metadata">

**Author:** ![szabgab](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/szabgab/32/1278_2.png) [@szabgab](https://forum.crystal-lang.org/u/szabgab)\
**Post date:** [July 12, 2021, 8:10pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/5 "2021-07-12T20:10:11Z")

</div>

Yeah, this solution with a macro works really well.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [July 12, 2021, 8:13pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/6 "2021-07-12T20:13:09Z")

</div>

Out of curiosity, what are you trying to do that uses this? Because ofc the macro could is literally the same as if you just did:

```auto
prs.name
prs.email

```

Then you don’t even need any macro code or anything…

EDIT: I.e. given that you need to manually specify what values to read in the macro, why not just manually call those methods on the object?

---

<div class="post-metadata">

**Author:** ![szabgab](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/szabgab/32/1278_2.png) [@szabgab](https://forum.crystal-lang.org/u/szabgab)\
**Post date:** [July 12, 2021, 8:21pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/7 "2021-07-12T20:21:32Z")

</div>

There are 4 attributes in my current real code and I run a regex on all 4 for a test to verify the values look good. I could of course do what you suggest and explicitly write down all 4, but it seemed to be too repetitive.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [July 12, 2021, 8:29pm UTC](https://forum.crystal-lang.org/t/struct-attribute-name-from-variable/3503/8 "2021-07-12T20:29:43Z")

</div>

I dunno, hardly seems worth it to bring in macros just to save typing 4 lines. But I don’t know the real context so if that helps then 👍. Do remember readability/simplicity go a long way in maintainability.
