# I'm on step zero on macros

**URL:** <https://discourse.julialang.org/t/im-on-step-zero-on-macros/115955>\
**Category:** New to Julia\
**Tags:** macros, strings\
**Created:** [June 21, 2024, 12:46am UTC](https://discourse.julialang.org/t/im-on-step-zero-on-macros/115955 "2024-06-21T00:46:41Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![martin\_sanchez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martin_sanchez/32/207525_2.png) [@martin\_sanchez](https://discourse.julialang.org/u/martin_sanchez)\
**Post date:** [June 21, 2024, 12:46am UTC](https://discourse.julialang.org/t/im-on-step-zero-on-macros/115955/1 "2024-06-21T00:46:41Z")

</div>

Hi, I have read most of the documentation, and trying to get my head around macros and how to write my own, but I read a thing like this

```julia
macro css_str(x::String)
     kvalues::Vector{SubString} = split(x, ";")
     Dict{Symbol, String}(begin
          splt = split(kval, ":")
          Symbol(splt[1]) => string(splt[2])
end for kval in kvalues)::Dict{Symbol, String}
end

```

And really simply do not get what is happening. Can you send me to a clear, concise guide to macros?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 21, 2024, 12:48am UTC](https://discourse.julialang.org/t/im-on-step-zero-on-macros/115955/2 "2024-06-21T00:48:49Z")

</div>

> [@martin\_sanchez](#):
>
> trying to get my head around macros and how to write my own

What are you trying to accomplish with a macro? It’s easier to give advice if you have a concrete goal in mind.

The first rule of writing macros is that you should [normally not write macros](https://discourse.julialang.org/t/how-to-warn-new-users-away-from-metaprogramming/35022).

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 21, 2024, 2:43am UTC](https://discourse.julialang.org/t/im-on-step-zero-on-macros/115955/3 "2024-06-21T02:43:16Z")

</div>

> [@stevengj](#):
>
> What are you trying to accomplish with a macro?

I’m pretty sure OP is going through a Medium article, which I cannot access as a non-member.

`css_str` splits a `;`-delimited string into entries, then it splits those entries into key-value pairs in a dictionary:

```julia
julia> css"a:bc;d:ef" # doesn't handle spaces
Dict{Symbol, String} with 2 entries:
  :a => "bc"
  :d => "ef"

```

You can do the same thing with a function, and in the vast majority of practical cases, you’d want it done by a function because macros are more limited. The importance of macros is that they work at parse-time.

What is parse-time? The Metaprogramming docs explains it but I’ll sum it up quickly. Everything starts as source code, the text you type. The parser has to change that into data Julia can understand. It is here that you encounter syntax errors; the parser realized the source code isn’t valid Julia.

Parsing source code doesn’t make many data types. Most code turns into `Symbol` and `Expr`. Literal values for `Int`, `Float64`, and `String` are also present; literal means you have to write the value directly in the source code. A macro’s inputs are limited to these types, though it’s acceptable to output any type. `css_str` thus only works if you write something like `css"a:bc;d:ef"`; if you had `x="a:bc;d:ef"`, there is no way to pass the variable `x` into `css_str` because only the symbol `:x` exists at parse-time.

So why use a macro if its inputs are limited? `css_str` is only a demonstration, it’s not representative of most macros. The usual use of macros is to transform code, `Expr` to `Expr`; a macro call would be equivalent to you manually writing the output into the source code. After a macro is done, parse-time is over and Julia _evaluates_ the output. If it’s a `Symbol` or `Expr`, it gets evaluated like any untransformed code you wrote; if it is or contains any other types, those types just pass through.

Here’s another demonstration (read: impractical) of a macro. Say I want a log5 for convenience, but there’s no built-in one. Simple, I’ll just use the log identity:

```julia
julia> log5(x) = log2(x)/log2(5)

```

Let’s look at what a call would be lowered to (a step before compiling):

```julia
julia> @code_lowered log5(5)
CodeInfo(
1 ─ %1 = Main.log2(x)
│ %2 = Main.log2(5)
│ %3 = %1 / %2
└── return %3
)

```

Hm, it’s doing `log2(5)`, but we could do that in advance. But I don’t want make a `const` global variable just for that. With a macro specially designed to work on `Expr` interpolated with more types or non-literals, I can compute the value before inserting it right into the method `Expr`:

```julia
julia> @eval log5(x) = log2(x)/$(log2(5))

```

And now the lowered code does:

```julia
julia> @code_lowered log5(5)
CodeInfo(
1 ─ %1 = Main.log2(x)
│ %2 = %1 / 2.321928094887362
└── return %2
)

```

Now for the impracticality, Julia’s compiler is smart enough to do function calls on constants or static parameters, including `log2(5)`, at compile-time if inferred and simple, and most constants are used more than once so they are actually worth `const` global variables. There are better examples of `@eval` code generation in the docs.
