DeepGetfield.jl

I developed a small utility package
DeepGetfield.jl
that provides the macro @deep composite.field which makes getfield look through a composite type recursively to find the specified field somewhere deep inside. I use it when I’ve run many experiments resulting in arrays of structs with arrays and structs inside, to find a particular field deep inside for analysis.

Don’t hesitate to criticise the implementation if you find it interesting!

Usage example

Pkg.clone("https://github.com/baggepinnen/DeepGetfield.jl")
using DeepGetfield

struct A
    x::Int
    y
    z
end

struct B
    xx
    yy
end

struct C
    zz
end

julia> a = A(2, 1., B(10., [C(1), C(2)])) # Create complex composite type

julia> dump(a) # Vizualize the structure and contents of a
A
  x: Int64 2
  y: Float64 1.0
  z: B
    xx: Float64 10.0
    yy: Array{C}((2,))
      1: C
        zz: Int64 1
      2: C
        zz: Int64 2

julia> getterfun = @deepf a.yy # This function acts as deep_getfield(a,:yy)

julia> getterfun(a) # Get field yy, equivalent to a.z.yy
2-element Array{C,1}:
 C(1)
 C(2)

julia>  @deep a.yy # Evaluate immediately without getting a function
2-element Array{C,1}:
 C(1)
 C(2)

julia> getterfun = @deepf a.zz # Getter for field zz, equivalent to getfield.(a.z.yy, :zz)

julia> getterfun(a) == [1,2] == getfield.(a.z.yy, :zz)
true
3 Likes

What does it do in case of an ambiguity?

  • If several fields inside the structure have the same name, the first field found (depth first) is returned and others ignored.
  • Arrays are looked through, but it is assumed that all elements in the array have the same field names. Only the first element is looked at during search. If the field is found inside an {Array / Array{Arrays}}, then the result will have that same structure

Wouldn’t breadth first be more natural?

Yeah in most circumstances it probably would. Depth first is easier to implement though and since that solved my problems I haven’t reached any further yet :see_no_evil:

Do you plan in future to support also getproperty accesor? That one is dynamic and that would be a killer usecase for accessing python classes or xml elements on the REPL.

1 Like

I probably will if I find it useful