# Modules, macros and global variables

**URL:** <https://discourse.julialang.org/t/modules-macros-and-global-variables/28754>\
**Category:** General Usage\
**Tags:** question\
**Created:** [September 14, 2019, 9:07am UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754 "2019-09-14T09:07:47Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [September 14, 2019, 9:07am UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/1 "2019-09-14T09:07:47Z")

</div>

Let’s say, I have:

1. Module `A` with global variable `RULES`, macro `@add_rule` and function `apply_all_rules()`.
2. Module `B` which defines some rules using `A.@add_rule` thus pushing them to `A.RULES`.
3. Module `C` in which we simply import `B`.

The behavior I want: once we call `import B`, all rules defined in `B` are added to `A.RULES` so that `A.apply_all_rules()` can see them.

Things that make it more complicated:

1. Module precompilation time != module load time (although I can use ` __init__ ()` to control this).
2. Macro expansion time != run time.
3. Global variables smell.

I have a concrete implementation of this strategy that doesn’t work, but before diving into it I’d like to know if somebody solved similar problems in a more elegant way.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [September 14, 2019, 9:13am UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/2 "2019-09-14T09:13:52Z")

</div>

For 1, you have ` __init__ ` as you say.  
For 2, the macro expansion shouldn’t as a side effect add anything to `RULES`, it should expand to code that adds the rule. This code is run during ` __init__ `.  
For 3, there is still only the `RULES` global variable, no?

Perhaps if you give a MWE it would be easier to see the concrete problem.

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [September 14, 2019, 9:20am UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/3 "2019-09-14T09:20:38Z")

</div>

I was afraid you’d say this 🙂 I’ll try to extract relevant parts of actual implementation preserving all the relevant details and come back to you!

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [September 14, 2019, 2:02pm UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/4 "2019-09-14T14:02:18Z")

</div>

While trying to make an MWE I actually fixed the issue. Not sure what was the reason but in addition to ` __init__ ()` I did 2 more important things:

1. Made sure I actually use latest versions of `A` and `B`. In previous attempts I called `up A` from pkg console of `B`, but didn’t actually commit changes to `A`, so at least in some tests I simply used wrong version of the package.
2. Replaced `push!($RULES, rule)` with a dedicated function. Previously I had:

```julia
module A

const RULES = []

macro add_rule(rule)
    return esc(quote
       # some magic in a caller module for which we need to escape the whole expression
       push!($RULES, rule)
    end)
end

end

```

I expected that `$RULES` will be expanded into actual object and pushing to this object will work regardless of a calling module. For whatever reason it didn’t work, but the following did:

```julia
module A

const RULES = []

add_rule_func(rule) = push!(RULES, rule)

macro add_rule(rule)
    return esc(quote
       # some magic in a caller module for which we need to escape the whole expression
       $add_rule_func(rule) # <-- this line changed
    end)
end

end

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [September 14, 2019, 2:28pm UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/5 "2019-09-14T14:28:43Z")

</div>

Just for my own understanding: Why do you need a macro at all to add rules to the RULES vector?

I.e., why not directly call the `add_rule` function everywhere?

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [September 14, 2019, 3:10pm UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/6 "2019-09-14T15:10:23Z")

</div>

1. It gives you convenient syntax. For an example of such rules take a look [here](https://github.com/dfdx/Yota.jl/blob/master/src/diffrules/basic.jl).
2. It gives you better control of execution. For example, as a first line of [actual implementation](https://github.com/dfdx/Yota.jl/blob/master/src/diffrules/diffrules.jl#L54-L65) of the mentioned macro I calculate the calling module (`B` in example above). Using function you would only be able to pass the module explicitly which would be quite verbose.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [September 14, 2019, 4:43pm UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/7 "2019-09-14T16:43:29Z")

</div>

Thanks for clarifying.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 15, 2019, 1:44am UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/8 "2019-09-15T01:44:07Z")

</div>

Does it really work? Unless you are calling `@add_rule` inside `B`’s ` __init__ `, I don’t think rules defined in `B` is available inside `C` (even after you do `using B`). This is because, IIUC, `@add_rule` is mutating data in `A` which is not saved in the precompilation cache of `B`. Of course, it’s OK if `A`, `B`, and `C` are all submodules of a same package. Otherwise, I think you’d need to define `B.RULES` and do `append!(A.RULES, RULES)` in `B. __init__ `. Alternatively, maybe you can define rules as methods.

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [September 15, 2019, 8:01am UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/9 "2019-09-15T08:01:34Z")

</div>

> [@tkf](#):
>
> Unless you are calling `@add_rule` inside `B` 's ` __init__ ` , I don’t think rules defined in `B` is available inside `C` (even after you do `using B` ).

Yes, so I indeed call `@add_rule` in `B. __init__ ()`. Thanks for adding the explanation why it’s needed, I think it’ll help other with similar needs!

> [@tkf](#):
>
> Alternatively, maybe you can define rules as methods.

Generally it’s a great option too, something that Julia is truly optimized for. But in my specific case I do a lot of symbolic manipulation which is hard to express via types and multimethods.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 15, 2019, 7:59pm UTC](https://discourse.julialang.org/t/modules-macros-and-global-variables/28754/10 "2019-09-15T19:59:55Z")

</div>

> [@dfdx](#):
>
> But in my specific case I do a lot of symbolic manipulation which is hard to express via types and multimethods.

I see that you are defining differentiation rules. I think I agree. My impression is that it’s challenging to support (say) broadcasting in the way ChainRules.jl works (i.e., using methods) because callers cannot “see” the definition. But I’ve been wondering if it’s possible to use some kind of more structured “thunks” in ChainRules.jl, maybe based on LazyArrays.jl, so that symbolic manipulations across differentiation rules is possible.

BTW, if you don’t want to use `add_rule_func`, I think this should work as well:

```julia
macro add_rule(rule)
    m = @ __MODULE__
    return esc(quote
       # some magic in a caller module for which we need to escape the whole expression
       push!($m.RULES, rule)
    end)
end

```
