# How does one programmatically examine the contents of a function?

**URL:** https://discourse.julialang.org/t/how-does-one-programmatically-examine-the-contents-of-a-function/109320
**Category:** General Usage
**Created:** [January 26, 2024, 9:53pm UTC](https://discourse.julialang.org/t/how-does-one-programmatically-examine-the-contents-of-a-function/109320 "2024-01-26T21:53:01Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![alex-s-gardner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alex-s-gardner/32/30210_2.png) [@alex-s-gardner](https://discourse.julialang.org/u/alex-s-gardner)
#### Post date: [January 26, 2024, 9:53pm UTC](https://discourse.julialang.org/t/how-does-one-programmatically-examine-the-contents-of-a-function/109320/1 "2024-01-26T21:53:02Z")

</div>

I would like to examine a user defined function to create a variable

example function

```julia
function foo(var)
  out = var.a.a1 .+ var.b.c3
  return out
end

```

in this case I would like to examine the code to identify that `var` has keys “a” and “b” and create the tuple (“a”,“b”)

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [January 27, 2024, 4:09am UTC](https://discourse.julialang.org/t/how-does-one-programmatically-examine-the-contents-of-a-function/109320/2 "2024-01-27T04:09:41Z")

</div>

```julia-repl
julia> e = :(function foo(var)
         out = var.a.a1 .+ var.b.c3
         return out
       end)
:(function foo(var)
      #= REPL[47]:1 =#
      #= REPL[47]:2 =#
      out = var.a.a1 .+ var.b.c3
      #= REPL[47]:3 =#
      return out
  end)

julia> sum_expr = e.args[2].args[3].args[2]
:(var.a.a1 .+ var.b.c3)

julia> sum_expr.args
3-element Vector{Any}:
 :.+
 :(var.a.a1)
 :(var.b.c3)

julia> sum_expr.args[2].args[1].args[2].value
:a

julia> sum_expr.args[3].args[1].args[2].value
:b

julia> (sum_expr.args[2].args[1].args[2].value, sum_expr.args[3].args[1].args[2].value)
(:a, :b)

julia> string.((sum_expr.args[2].args[1].args[2].value, sum_expr.args[3].args[1].args[2].value))
("a", "b")

```

We could turn it into a macro as follows.

```julia-repl
julia> macro metafoo(e)
           sum_expr = e.args[2].args[3].args[2]
           string.((sum_expr.args[2].args[1].args[2].value, sum_expr.args[3].args[1].args[2].value))
       ("a", "b")
       end
@metafoo (macro with 1 method)

julia> @metafoo function foo(var)
         out = var.a.a1 .+ var.b.c3
         return out
       end
("a", "b")

```

Perhaps you could not convince the user to use a macro. Then you might be able to parse through the lowered code as follows.

```julia
julia> lowered = code_lowered(foo, Tuple{NamedTuple})[1]
CodeInfo(
1 ─ %1 = Main.:+
│ %2 = Base.getproperty(var, :a)
│ %3 = Base.getproperty(%2, :a1)
│ %4 = Base.getproperty(var, :b)
│ %5 = Base.getproperty(%4, :c3)
│ %6 = Base.broadcasted(%1, %3, %5)
│ out = Base.materialize(%6)
└── return out
)

julia> lowered.code[2].args[3].value
:a

julia> lowered.code[4].args[3].value
:b

julia> lowered.code[2].args[3].value, lowered.code[4].args[3].value
(:a, :b)

julia> string.((lowered.code[2].args[3].value, lowered.code[4].args[3].value))
("a", "b")

```
