# Macros and forall

**URL:** <https://forum.crystal-lang.org/t/macros-and-forall/3409>\
**Category:** Help & Support\
**Created:** [June 21, 2021, 7:45pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409 "2021-06-21T19:45:34Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![henrikac](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/henrikac/32/3079_2.png) [@henrikac](https://forum.crystal-lang.org/u/henrikac)\
**Post date:** [June 21, 2021, 7:45pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/1 "2021-06-21T19:45:34Z")

</div>

Hi,

I’m trying to create a macro that takes generic types as arguments but I keep getting `Error: undefined constant`.

Example code:

```auto
macro my_macro(t1, t2)
  # code ...
end

class Foo(T)
  def bar(x : U) forall U
    # code ...
    bar_var = my_macro(T, U) # <-- Error: undefined constant U
    # more code ...
  end
end

```

I have no idea why I get this error because, if I understand this [this](https://github.com/crystal-lang/crystal/issues/7737#issuecomment-489572166) correctly, it should be possible?

---

<div class="post-metadata">

**Author:** ![Exilor](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/exilor/32/780_2.png) [@Exilor](https://forum.crystal-lang.org/u/Exilor)\
**Post date:** [June 21, 2021, 8:02pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/2 "2021-06-21T20:02:48Z")

</div>

It is possible but the code you provided doesn’t reproduce the error you mentioned.  
Filling in the macro with some arbitrary code:

```auto
macro my_macro(t1, t2)
  {{t1}}.to_s + {{t2}}.to_s
end

class Foo(T)
  def bar(x : U) forall U
    # code ...
    bar_var = my_macro(T, U)
    # more code ...
  end
end

Foo(Int32).new.bar("") # => "Int32String"

```

---

<div class="post-metadata">

**Author:** ![henrikac](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/henrikac/32/3079_2.png) [@henrikac](https://forum.crystal-lang.org/u/henrikac)\
**Post date:** [June 21, 2021, 8:11pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/3 "2021-06-21T20:11:05Z")

</div>

That’s weird.

Here is my actual code - maybe I missed something?

```auto
macro generate_vector(t1, t2)
  {% if !(t1.resolve < Float) && t2.resolve < Float %}
    # code ...
  {% else %}
    # code ...
  {% end %}
end

class Vector(T)
  def +(other : Vector(U)) forall U
    if self.size != other.size
      raise ArgumentError.new("vectors must be same size")
    end

    vec = generate_vector(T, U)
    # Error: undefined constant U :/
    self.each_with_index do |elem, i|
      vec << elem + other[i]
    end
    return vec
  end
end

```

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [June 21, 2021, 8:13pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/4 "2021-06-21T20:13:41Z")

</div>

Hi and welcome!

If you copy all of the code you are sharing so far into a text editor, and run `crystal ...` on it, it compiles fine.

Can you share some code that reproduces the error you are seeing?

---

<div class="post-metadata">

**Author:** ![Exilor](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/exilor/32/780_2.png) [@Exilor](https://forum.crystal-lang.org/u/Exilor)\
**Post date:** [June 21, 2021, 8:22pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/5 "2021-06-21T20:22:11Z")

</div>

Try replacing `generate_vector(T, U)` with `generate_vector({{T}}, {{U}})`

---

<div class="post-metadata">

**Author:** ![henrikac](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/henrikac/32/3079_2.png) [@henrikac](https://forum.crystal-lang.org/u/henrikac)\
**Post date:** [June 21, 2021, 8:23pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/6 "2021-06-21T20:23:52Z")

</div>

created a branch and pushed it to github.

[repo](https://github.com/henrikac/linalg/tree/macro-generators)

The code can be found in `src/linalg/vector.cr` and `src/linalg/helpers/generators.cr`

What I’m trying to is to replace the two generator methods (`generate_vector` and `generate_matrix`) with the macro code at the top in `generators.cr`

I’m not sure if this is an important information but I get the error when I run `crystal spec`

---

<div class="post-metadata">

**Author:** ![henrikac](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/henrikac/32/3079_2.png) [@henrikac](https://forum.crystal-lang.org/u/henrikac)\
**Post date:** [June 21, 2021, 8:29pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/7 "2021-06-21T20:29:45Z")

</div>

That gave me a new error but I got right back to `undefined constant U` when the error was fixed.

---

<div class="post-metadata">

**Author:** ![Exilor](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/exilor/32/780_2.png) [@Exilor](https://forum.crystal-lang.org/u/Exilor)\
**Post date:** [June 21, 2021, 8:41pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/8 "2021-06-21T20:41:39Z")

</div>

Change the following:

in generators.cr:

```auto
macro generate_vector(t1, t2)
  {% if !(t1.resolve < Float) && t2.resolve < Float %}
    Linalg::Vector({{t2.resolve}}).new
  {% else %}
    Linalg::Vector({{t1.resolve}}).new
  {% end %}
end

```

in vector.cr:

`generate_vector(T, U)` to `generate_vector({{T}}, {{U}})`

It worked for me.

---

<div class="post-metadata">

**Author:** ![henrikac](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/henrikac/32/3079_2.png) [@henrikac](https://forum.crystal-lang.org/u/henrikac)\
**Post date:** [June 21, 2021, 8:44pm UTC](https://forum.crystal-lang.org/t/macros-and-forall/3409/9 "2021-06-21T20:44:46Z")

</div>

You are my hero! I have been stucked on this almost all day.

Thank you!
