# Capturing where-clause using MacroTools

**URL:** <https://discourse.julialang.org/t/capturing-where-clause-using-macrotools/33223>\
**Category:** General Usage\
**Tags:** metaprogramming\
**Created:** [January 11, 2020, 1:00am UTC](https://discourse.julialang.org/t/capturing-where-clause-using-macrotools/33223 "2020-01-11T01:00:11Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [January 11, 2020, 1:00am UTC](https://discourse.julialang.org/t/capturing-where-clause-using-macrotools/33223/1 "2020-01-11T01:00:11Z")

</div>

Hi there! I wonder if anyone can help me with this… I would like to write a macro that takes a function definition and modifies it to do something at the beginning and at the end. So I cooked up this MWE but I got stuck on using the where-clause from what it was captured:

```julia
using MacroTools
macro foo(ex)
    @capture(ex, function f_(args__) where T_ body_ end) || error("bad ex")
    @info "captured" f args T body
    newex = :(
        function $(esc(f))($(esc(args...))) where $T
            println("pre")
            $(esc(body))
            println("post")
        end
    )
    # @info "newex" newex
    return newex
end

```

And it’s give me this error:

```julia
julia> @foo function wat(x::T) where {T <: Number} 
           @info "variables" x 
           return x + 1
       end
┌ Info: captured
│ f = :wat
│ args =
│ 1-element Array{Any,1}:
│ :(x::T)
│ T = :(T <: Number)
│ body =
│ quote
│ #= REPL[23]:2 =#
│ #= REPL[23]:2 =# @info "variables" x
│ #= REPL[23]:3 =#
│ return x + 1
└ end
ERROR: UndefVarError: T not defined

```

What am I missing? Thanks

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [January 11, 2020, 1:04am UTC](https://discourse.julialang.org/t/capturing-where-clause-using-macrotools/33223/2 "2020-01-11T01:04:42Z")

</div>

I don’t currently have time to figure what what went wrong in your code, but I would recommend just using `MacroTools.splitdef` instead:

```julia
julia> using MacroTools: splitdef

julia> d = splitdef(:(function wat(x::T) where {T <: Number}
                          @info "variables" x
                          return x + 1
                      end))
Dict{Symbol,Any} with 5 entries:
  :name => :wat
  :args => Any[:(x::T)]
  :kwargs => Any[]
  :body => quote…
  :whereparams => (:(T <: Number),)

julia> d[:name]
:wat

julia> d[:body]
quote
    #= REPL[51]:2 =#
    #= REPL[51]:2 =# @info "variables" x
    #= REPL[51]:3 =#
    return x + 1
end

```

You might also want to check out `MacroTools.combinedef` to put such dictionaries back together into an expr.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [January 11, 2020, 1:20am UTC](https://discourse.julialang.org/t/capturing-where-clause-using-macrotools/33223/3 "2020-01-11T01:20:48Z")

</div>

You need to change the `$T` in `newex` to `$(esc(T))` as well.

---

<div class="post-metadata">

**Author:** ![tk3369](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tk3369/32/2824_2.png) [@tk3369](https://discourse.julialang.org/u/tk3369)\
**Post date:** [January 11, 2020, 2:29am UTC](https://discourse.julialang.org/t/capturing-where-clause-using-macrotools/33223/4 "2020-01-11T02:29:48Z")

</div>

`splitdef` and `combinedef` is VERY nice!
