Struct attribute name from variable

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?

struct Person
  getter name : String
  getter email : String

  def initialize(@name, @email)

prs ="Foo Bar", "")
p! prs

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

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

case field
when "name" then
when "email" then

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

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

{% for field in ["name", "email"] %}
  prs.{{ }}
{% end %}
1 Like

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.

Yeah, this solution with a macro works really well.

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:

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?

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.

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 :+1:. Do remember readability/simplicity go a long way in maintainability.

1 Like