# Manipulating expressions with macros

**URL:** <https://discourse.julialang.org/t/manipulating-expressions-with-macros/39229>\
**Category:** General Usage\
**Tags:** macros\
**Created:** [May 10, 2020, 1:54pm UTC](https://discourse.julialang.org/t/manipulating-expressions-with-macros/39229 "2020-05-10T13:54:33Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [May 10, 2020, 1:54pm UTC](https://discourse.julialang.org/t/manipulating-expressions-with-macros/39229/1 "2020-05-10T13:54:33Z")

</div>

Hi. I’m having trouble defining a macro which manipulates expressions containing `$`’s. It’s best illustrated by example:

Is it possible to define a macro `@newrule` such that

```julia
for op ∈ (+, -)
	@newrule $op(a, 0) => a
end

```

expands to a function call `newrule(::Expr)`

```julia
for op ∈ (+, -)
	newrule(:($op(a, 0) => a))
end

```

where `op` is in the local scope? So at run-time this is should be equivalent to:

```julia
newrule(:(a + 0 => a))
newrule(:(a - 0 => a))

```

It seems like this should certainly be possible, since the macro performs a purely syntactical transformation at parse-time—but here’s my trouble:

If we do

```julia
using MacroTools: postwalk

macro newrule(expr)
	escaped = postwalk(expr) do node
		if node isa Expr && node.head == :$
			esc(node.args[1])
		else
			node
		end
	end
	escaped
end

```

then the macro call `@newrule $op(a, 0) => a` will return _and evaluate_ the expression `:( a + 0 => a )`, which errors since `a` is undefined. But we want the macro to return an expression _which evaluates to the expression_, so that the run-time value is the expression `:( a + 0 => a )`. If I do

```julia
		...
	end
	QuoteNode(escaped)
end

```

then the macro call results in a run-time expression, but the interpolation is quoted also, so that the run-time value is `:(($(Expr(:escape, :op)))(a, 0))`.

Thanks for your help!

---

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [May 10, 2020, 2:46pm UTC](https://discourse.julialang.org/t/manipulating-expressions-with-macros/39229/2 "2020-05-10T14:46:28Z")

</div>

I did it! The macro I sought was:

```julia
macro newrule(expr)
	quote $(Expr(:quote, expr)) end
end

```

Now we have, as desired:

```julia
julia> [@newrule $op(a, 0) => a for op ∈ (+, -)]
2-element Array{Expr,1}:
 :((+)(a, 0) => a)
 :((-)(a, 0) => a)

```

`QuoteNode(expr)` was a red herring. I thought this played the role of `Expr(:quote, expr)`, but it does not, and I wasn’t exactly sure what `QuoteNode` _was_ meant for until I read [this issue.](https://github.com/JuliaLang/julia/issues/6104)
