# Understanding Macros – A macro to decorate a Type

**URL:** <https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204>\
**Category:** New to Julia\
**Created:** [July 6, 2018, 7:36am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204 "2018-07-06T07:36:37Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [July 6, 2018, 7:36am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/1 "2018-07-06T07:36:37Z")

</div>

I read about macros the last few days and I am starting to love the concept. Due to their powerfulness, I still seem to not be able to get my ideas into an implemented Macro (actually in two cases and this is the first).

Let’s assume I have a decorator pattern like parametrised type like

```julia
abstract type P end
immutable struct Q{T <: Float64} <: P
    field::T
end
immutable struct DecoQ{S <: Q{T} where T} <: Q
  base::Q{T}
  info::Int
  DecoQ(t::T) = new(Q(t),0) 
end

get(t::Q{T} where T) = t.field
get(t::DecoQ{S <: Q{T} where T}) = get(t.base)

myF(q::T where T<:Q, i::Int)::Q = Q(i*Q.flield)
function myF(q::T where T <: DecoQ, i::Int)
  info = info+1
  return DecoQ(myF(q.base,i),info)
end

```

So if I initialise a value to be `DecoQ` it is a `Q` decorated with another field and with the getters I have a proper access to the field (I could also write that to access `Q` instead of it’s field, it’s to “unpeel” the decorator(s)).

With this pattern (adapted from object oriented, I’d be open for a more Julia-type decorator), I would like to have a `@macro` that easily starts the procedure decorated, i.e. if I have

```julia
q::Q{Float64} = Q(0.1337)
qnew = myF(q,23)

```

I would like to be able to change that last line to

```julia
qnew = @decorateQ myF(q,23) 

```

That changes the call to `myF( DecoQ(q,23), 23)` for example (or even calculate on `i` for example changing it to `myF( DecoQ(q,46),23)` ).  
So I can describe what I would like to have, but for the last days I still haven’t understood macros enough to know how to do that. Especially hooking into arguments and local variables is something I haven’t understood yet – so maybe if somebody could solve this, I’d learn more about macros (or give me a hint where to find such ideas).

edit: the first `<: P` was mistyped to be `<: E`, `Float` was corrected to `Float64`.

---

<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:** [July 6, 2018, 8:02am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/2 "2018-07-06T08:02:57Z")

</div>

You can think of macros as functions that take syntax and return syntax. These “functions” are also not run during runtime but during a special time in the pipeline called “macro expansion”.

So the input syntax you have is:

```julia
myF(q,23) 

```

We can expose the internals of the input syntax with `dump`:

```julia
julia> dump(:(myF(q,23)))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol myF
    2: Symbol q
    3: Int64 23
  typ: Any

```

We can now rewrite this syntax to the desired output syntax with a macro:

```julia
macro decorate(expr::Expr)
    # validate input
    @assert expr.head === :call
    @assert length(expr.args) == 3
    
    f, q, i = esc.(expr.args)
    return quote
        $f(DecoQ($q, $i), $i)
    end 
end

```

To check what it expands to

```julia
julia> @macroexpand @decorate myF(q,23)
quote
    myF((Main.DecoQ)(q, 23), 23)
end

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 6, 2018, 8:05am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/3 "2018-07-06T08:05:53Z")

</div>

In addition, you probably need to fix a couple of minor things:

1. probably an `abstract type E end` is missing,
2. you did not define `Float`, did you mean `Float64`?,
3. you can’t subtype `Q`, as it is a concrete type,
4. you are not using the `S` at all in `DecoQ`, are you sure you need it?
5. `T` is not bound in `DecoQ` (captured by the `where` clause, what did you want to do here?

Also, `struct`s are immutable by default.

---

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [July 6, 2018, 8:11am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/4 "2018-07-06T08:11:25Z")

</div>

Very nice! Thanks for this very fast answer. That looks easier to implement than I thought!  
Just one further question – is it possible to distinguish either the function I get (can I check that it’s called f?) or the type of argument (that the second one is a `::Q`?).  
I think the second one would be easier, because if I have further functions  
`g(p::Something, f::Q, t::Float)` I maybe want to decorate the second argument, not the first,  
but even more (hence the type check) if `q`already _is_ a `::DecoQ` I don’t want to decorate further/again.

Thanks again for that fast answer – but I also see, I have to read a lot more about macros - they really seem to be nice (and to some extend also mean, I suppose).

---

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [July 6, 2018, 8:20am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/5 "2018-07-06T08:20:31Z")

</div>

Thanks for the remarks – the code is trying to mimic a more complicated situation.  
With the first two, you are completely right, I corrected `E` to also be `P` and `Float` is `Float64`  
For the third – yes that’s always bothering me, that I can’t build a Hierarchy of concrete types – I would like to soooo much,  
but then the super type has to be `P` for them.

For the fourth – no I am not sure, maybe it’s enough to do `DecoQ{T}`, because the idea is to just introduce an additional field to `Q` (as decoration)  
I want `DecoQ`to b kind of. So also for the constructor it should probably read `DecoQ(t::T) where T = new (Q(t),0)`.

While this typing is quite nice, I am still getting used to it.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 6, 2018, 8:36am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/6 "2018-07-06T08:36:00Z")

</div>

> [@kellertuer](#):
>
> I want `DecoQ` to b kind of.

Sorry, I fail to understand this.

If you are [using a concrete field type for performance](https://docs.julialang.org/en/latest/manual/performance-tips/#Avoid-fields-with-abstract-type-1), just define it like this:

```julia
struct DecoQ{S <: Q}
  base::S
  info::Int 
end

DecoQ(base::Q) = DecoQ(base, 0)

```

Otherwise, using an inner constructor with `info = 0` in an _immutable_ type is pretty meaningless, since you won’t be able to change it.

Generally, while macros are a very powerful feature, I would recommend that you try to learn the language first, see if you can implement your ideas without any source transformations (you usually can, parametric types combined with multiple dispatch is very powerful), then when take a look at macros again.

---

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [July 6, 2018, 8:45am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/7 "2018-07-06T08:45:42Z")

</div>

Thanks, you’re right, that `decoQ` can not be immutable of course.

My general motivation to look at a macro for this is that:  
If I start with some value fo `decoQ` I can make sure it is after that always `decoQ`. That’s of course possible with parametric types and the very nice feature of multiple dispatch (hence the getters for example).

But If I have a longer notebook somewhere and start computing with my favourite `Q` types and after a while I notice (somewhere in cell 45) that the following I would like to execute the following decorated, but I am not sure whether it already is and such – the macro is a good and easy access, because I can just add `@decorate` to that line.

And maybe – while I am getting used to parametric types and multiple dispatch (actually I did Mathematica for quite some time which does multiple dispatch too, just with a different name) I maybe want to _also_ learn about macros. Sorry, If that sometimes then leads to questions that for an expert might look a little dumb.

_Edit:_ Oh I just saw – in my project the decorated value _is_ actually not changing, so it#s only a value available at creating `decoQ` that I would like to keep track of, but not to change it (even worse - changing it would make the decorator useless) – so for my transcribed example you’re right, but I was maybe just not awake enough this morning.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 6, 2018, 8:57am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/8 "2018-07-06T08:57:29Z")

</div>

> [@kellertuer](#):
>
> want to _also_ learn about macros. Sorry, If that sometimes then leads to questions that for an expert might look a little dumb.

I did not mean to imply that you should not learn about macros, or that there is any problem with your questions.

Just that Julia can be overwhelming initially, and it is already very powerful without macros. IMO macros should be used when they provide the most convenient alternative, which cannot be implemented without them and you truly need a source transformation. But to see that, one has to be aware of what Julia (w/o macros) can offer. So some experience is valuable.

Also, macros can be difficult to debug, and specifically hygiene (`esc`) can be tricky.

---

<div class="post-metadata">

**Author:** ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)\
**Post date:** [July 6, 2018, 9:36am UTC](https://discourse.julialang.org/t/understanding-macros-a-macro-to-decorate-a-type/12204/9 "2018-07-06T09:36:39Z")

</div>

Of course this question is also a thought about, whether that’s the right way to go. In short, I am convinced, that with the macro I can spare to recreate data (say within a notebook and creation takes an hour) by using a macro to decorate instead of a new initialisation (and computation) of the data.  
But maybe I am also wrong – than this thread is just to learn about macros themselves.
