Macro expansion on create method in the for loop create duplicate method?

# 1.cr

{% for name, index in ["foo", "bar", "baz"] %}
  def {{name.id}}
    {{index}}
  end
  {% debug %}
{% end %}

The output of crystal run 1.cr is:

def foo
  0
end
def foo
  0
end

def bar
  1
end
def foo
  0
end

def bar
  1
end

def baz
  2
end

As above, the method foo has been defined 3 times, method bar defined 2 times, method baz define 1 times.

The correct(expected) result is each method should only be defined once, right?

def foo
  0
end

def bar
  1
end

def baz
  2
end

Is it for loop doing something wrong, or {% debug%}?


 ╰─ $ crystal version
Crystal 1.13.1 [0cef61e51] (2024-07-12)

LLVM: 18.1.8
Default target: x86_64-pc-linux-gnu

The {% debug %} is evaluating each iteration of the for loop. You probably want to do this instead:

{% begin %}
  {% for name, index in ["foo", "bar", "baz"] %}
    def {{name.id}}
      {{index}}
    end
  {% end %}
  {% debug %}
{% end %}

So it only prints the final result of the loop.

Thanks for explain. i understood now, this issue caused by the {% debug %} be evaluate 3 times, but only the last time is what I want.

1 Like