Search code examples
reflectioncrystal-lang

Compile time reflection over type members


I'd like to write a macro which will let me perform some operations on each attribute of a record, like deserialize a CSV row into the record instance with proper type casting. Where do I start from?


Solution

  • This is a very broad question. So I'll answer two different ones.

    How can I avoid code duplication using macros?

    Simple, just use a loop!

    numbers = [5, 3, 2, 1]
    
    {% for operator in [:*, :+, :/, :-] %}
      numbers.map! {|number| number {{operator.id}} 23 }
    {% end %}
    
    p numbers
    
    [-17, -19, -20, -21]
    

    How can I get a list of all instance variables of a type at compile time?

    Via TypeNode#instance_vars!

    struct Bag 
      property has_wallet : Bool = false
      property has_bottle : Bool = false
      property has_keys : Bool = false
    end
    
    def fill_bag(bag)
      {% for name in Bag.instance_vars %}
      bag.{{name.id}} = true
      {% end %}
      bag
    end
    
    p fill_bag(Bag.new)
    
    Bag(@has_wallet=true, @has_bottle=true, @has_keys=true)