How to return all properties of a class/struct in a string delimited list?

Example code:

class Portal
  property zone_to = 0
  property x = 0f32
  property y = 0f32
  property owner_id = 0

  def initialize(@x, @y, @owner_id, @zone_to)
  end

  def prop_string()
    "#{zone_to},#{x},#{y},#{owner_id}"
  end
end

p = Portal.new(1f32,1f32,1,1)

pp p.prop_string

However, is it possible to do this dynamically so we don’t have to hard-code the variable in prop_string each time we add a new property to the class?

edit: Hmm… something something macros :stuck_out_tongue:

DAMN! I think I got it!

class Portal
  property zone_to = 0
  property x = 0f32
  property y = 0f32
  property owner_id = 0

  def initialize(@x, @y, @owner_id, @zone_to)
  end
  
  def prop_string()
    array_string = Array(String).new
    {% for v in @type.instance_vars %}
      array_string << {{v}}.to_s
     {% end %}
    array_string.join(",")
  end
end

p = Portal.new(1f32,1f32,1,1)

pp p.prop_string

All by myself :slight_smile: Any thoughts / improvements?

edit: Damn, macros are aweeesomeee!

1 Like

Could simplify it to {{@type.instance_vars.map(&.id)}}.join(','). This way the only thing that is happening at runtime is the join.

1 Like

Oh neato! Yeah that’s way nicer and easier to read lol, ty

You can even avoid the runtime join by doing it in the macro. {{@type.instance_vars.map(&.id).join(‘,’)}} will perform the join at compile time and you don’t even have to pay the runtime cost of allocating the string.

That wouldn’t work. That would result in the string being the names of each property joined together, like "zone_to,x,y,owner_id". It has to happen at runtime as it needs to join the runtime values of each ivar.

1 Like

Ah, sorry. I thought the names are what we were talking about. :joy:

You could even use a tuple, to avoid allocating an array!

{% begin %}
  { {{@type.instance_vars.map(&.id).splat}} }.join(',')
{% end %}
3 Likes

Yeah, I probably should have wrote property values :laughing:

More explicit hahaha

1 Like