# For loop inside macro quote block

**URL:** <https://discourse.julialang.org/t/for-loop-inside-macro-quote-block/18953>\
**Category:** New to Julia\
**Created:** [December 24, 2018, 3:22am UTC](https://discourse.julialang.org/t/for-loop-inside-macro-quote-block/18953 "2018-12-24T03:22:59Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul\_McVay](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_mcvay/32/4307_2.png) [@Paul\_McVay](https://discourse.julialang.org/u/Paul_McVay)\
**Post date:** [December 24, 2018, 3:22am UTC](https://discourse.julialang.org/t/for-loop-inside-macro-quote-block/18953/1 "2018-12-24T03:22:59Z")

</div>

I apologize that this question may not generalize to many other people’s problems but I’m having a lot of trouble coming up with a macro. Say for example, I have this dictionary

```julia
dict = Dict("a" => 1, "b" => Dict("inner" => "test"))

```

I want to create a macro `getField(fields...)` that generates a function for me depending on the number of arguments passed. For example, if one argument `@getField "a" ` is passed it returns the function

```julia
x::Dict{String, Any} -> begin
  if !("a" in keys(x))
    return ""
  end
  return x["a"]
end

```

And if two arguments are passed `@getField "b" "inner"` then it returns the function

```julia
x::Dict{String, Any} -> begin
  if !("b" in keys(x))
    return ""
  end
  if !("inner" in keys(x["b"]))
    return ""
  end
  return x["b"]["inner"]
end

```

Basically, go through each layer of the dictionary and make sure the field is there and if it not there, return an empty string. My code so far that fails horribly is

```julia
macro getField(fields...)
    quote
        x::Dict{String, Any} -> begin
            if !($(fields[1]) in keys(x))
                return ""
            end
            tmp = $(fields[1])
            if $(length(fields)) > 1
                for f in $(fields[2:end])
                    if !(f in tmp)
                        return ""
                    end
                    tmp = tmp[f]
                end
            end
        end
    end
end

```

Can someone help me understand how to loop over the fields passed to create the function?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 24, 2018, 3:47am UTC](https://discourse.julialang.org/t/for-loop-inside-macro-quote-block/18953/2 "2018-12-24T03:47:46Z")

</div>

This actually doesn’t need to be a macro. Instead, you can write a recursive function which will be easier to debug and maintain:

```julia
julia> function my_get_field(d, fields...)
         if first(fields) in keys(d)
           my_get_field(d[first(fields)], Base.tail(fields)...)
         else
           ""
         end
       end
my_get_field (generic function with 1 method)

julia> my_get_field(x) = x # handle the case when no additional fields are left
my_get_field (generic function with 2 methods)

julia> dict = Dict("a" => 1, "b" => Dict("inner" => "test"))
Dict{String,Any} with 2 entries:
  "b" => Dict("inner"=>"test")
  "a" => 1

julia> my_get_field(dict, "a")
1

julia> my_get_field(dict, "b", "inner")
"test"

julia> my_get_field(dict, "b", "not here")
""

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 24, 2018, 4:15am UTC](https://discourse.julialang.org/t/for-loop-inside-macro-quote-block/18953/3 "2018-12-24T04:15:40Z")

</div>

Or, if you want something closer to your original implementation (but still with no need to write a macro):

```julia
julia> function my_get_field_2(fields...)
         x::Dict{String, Any} -> begin
           for field in fields
             if !(field in keys(x))
               return ""
             else
               x = x[field]
             end
           end
           return x
         end
       end
my_get_field_2 (generic function with 1 method)

julia> dict = Dict("a" => 1, "b" => Dict("inner" => "test"))
Dict{String,Any} with 2 entries:
  "b" => Dict("inner"=>"test")
  "a" => 1

julia> dict |> my_get_field_2("a")
1

julia> dict |> my_get_field_2("b", "inner")
"test"

```
