# How do classes interact with macros?

**URL:** <https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134>\
**Category:** Offtopic\
**Created:** [September 20, 2019, 2:59am UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134 "2019-09-20T02:59:00Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![girng\_github](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/girng_github/32/571_2.png) [@girng\_github](https://forum.crystal-lang.org/u/girng_github)\
**Post date:** [September 20, 2019, 2:59am UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134/1 "2019-09-20T02:59:00Z")

</div>

Example code:

```auto
class Player
  property health = 10
end

p = Player.new

macro adjust_nodes(option, client)
  {{client}}.health {{option.id}} 10
end

adjust_nodes("+=", p)

5.times do |x|
  pp adjust_nodes("+=", p)
end

5.times do |x|
  pp adjust_nodes("-=", p)
end

```

My questions:

- How many `adjust_nodes` methods are being created? 1 or 10?
- Is the `Player` being passed by reference, or passed by value?

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [September 20, 2019, 3:05am UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134/2 "2019-09-20T03:05:34Z")

</div>

Do realize macros != methods. Macros just define code that will be expanded at compile time. I.e. your example is essentially no different than:

```auto
class Player
  property health = 10
end

p = Player.new

p.health += 10

5.times do |x|
  pp p.health += 10
end

5.times do |x|
  pp p.health -= 10
end

```

The `Player` class isnt being passed at all. You’re just interacting with the getter.

---

<div class="post-metadata">

**Author:** ![girng\_github](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/girng_github/32/571_2.png) [@girng\_github](https://forum.crystal-lang.org/u/girng_github)\
**Post date:** [September 20, 2019, 3:11am UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134/3 "2019-09-20T03:11:29Z")

</div>

Damn, that makes sense. I still can’t believe why macros are so damn complex for me, thanks for being patient.

I still am not unsure if I should use them for my use case (in that github thread). I’m going to fiddle around with them some more and just refer back to this thread.

---

<div class="post-metadata">

**Author:** ![girng\_github](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/girng_github/32/571_2.png) [@girng\_github](https://forum.crystal-lang.org/u/girng_github)\
**Post date:** [September 20, 2019, 4:24am UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134/4 "2019-09-20T04:24:27Z")

</div>

```auto
macro adjust_skill_nodes(nodes, operator, client)
  {{nodes}}.each do |sid|
    if (skill_node = TreeData[sid]?) && (main_node_type = NodeTypes[skill_node["type"]]?)
      main_node_type.modifications.each do |mod, value|
        case mod
        when "strength"
          {{client}}.strength {{operator.id}} value
        when "increased_attack_speed"
          {{client}}.increased_attack_speed {{operator.id}} (value / 100.00)
        when "health"
          {{client}}.health {{operator.id}} value
        when "health_regen"
          {{client}}.health_regen {{operator.id}} (value / 100.00)
        end
      end

      puts {{client}}
    else
      raise "Skill tree error.. this is bad. skill id: #{sid} does not exist on the server!"
    end
  end
end

```

Does this code stand out to anyone (any improvements maybe?)

I use

```auto
        adjust_skill_nodes(nodes_added, "+=", client)

```

When a player creates/joins a game or when they allocate points on their passive tree.

So far it’s working good. Any possible issues?

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [September 20, 2019, 1:15pm UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134/5 "2019-09-20T13:15:48Z")

</div>

You know my opinion on this. There are some improvements you could make but it would require some not so trivial changes.

For this use case it seems like an okay solution as you’re able to reuse some seemly complex logic. The only issue you would run into is when/if logic is required for one adjustment and not the other.

---

<div class="post-metadata">

**Author:** ![girng\_github](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/girng_github/32/571_2.png) [@girng\_github](https://forum.crystal-lang.org/u/girng_github)\
**Post date:** [September 20, 2019, 10:46pm UTC](https://forum.crystal-lang.org/t/how-do-classes-interact-with-macros/1134/6 "2019-09-20T22:46:31Z")

</div>

Yeah, I did `pp {{client}}` and my console was bombarded with messages. I originally thought it was passing all that data into the macro (by copy) instead of by reference, each time the method is executed ;S. However, `pp` expands and prints out all the client’s properties (even properties that reference other classes). So it would have acted the same even if it wasn’t in a macro. This is why I was worried, but I shouldn’t have been.

“expanded at compile time” is what helped. I always thought it was just duplicating a method that has different functionality based on how you set up the macro. But in reality, wherever a macro is located at in your code, just expands at compile time.

Kind of like throwing darts at a dartboard. Then, those darts expand into code. Those expanded darts are now your macros.
