The Crystal Programming Language Forum

Ruby porting question - dynamic methods

Hi, I’m attempting to port a ruby gem to a shard, but I’ve run into a block, specifically how to do the following in crystal:

ops = %w[fill stroke fill_and_stroke]
    shapes = %w[
      line_to curve_to rectangle rounded_rectangle line horizontal_line
      horizontal_rule vertical_line curve circle_at circle ellipse_at ellipse
      polygon rounded_polygon rounded_vertex
    ]

    ops.product(shapes).each do |operation, shape|
      class_eval <<-METHOD, __FILE__, __LINE__ + 1
        def #{operation}_#{shape}(*args)    # def fill_polygon(*args)
          #{shape}(*args)                   #   polygon(*args)
          #{operation}                      #   fill
        end                                 # end
      METHOD
    end

I thought I might be able to use a macro, but my attempts so far have been unsuccessful, mainly because it looks like macros always want literal args not Vars.(?)
Any suggestions would be most helpful.

{% for op in %w[fill stroke fill_and_stroke] %}
  {% for shape in %w[
                    line_to curve_to rectangle rounded_rectangle line horizontal_line
                    horizontal_rule vertical_line curve circle_at circle ellipse_at ellipse
                    polygon rounded_polygon rounded_vertex
                  ] %}
    
    def {{op.id}}_{{shape.id}}(*args)
      {{shape.id}}(*args)
      {{op.id}}
    end
  {% end %}
{% end %}

This should do it.

1 Like

Ah yes, that makes sense. Thank you!