Get any object properties by name

Hello, I need to get object property values by their names.
The order of the values must match the order of the property names.
Can it be done better?

struct TestObject
    a
    b
    c
end

object = TestObject(1,2,3)

function getproperties(object::T, properties::Union{Symbol, Tuple{Vararg{Symbol}}, AbstractVector{Symbol}}) where T
    values = []
    for property in properties
        push!(values, getproperty(object, property))
    end
    return values
end

getproperties(object, (:a,:c,:b))

As a generator

getproperties(object, properties) = 
    (getproperty(object, property) for property in properties)
collect(getproperties(object, (:a,:c,:b)))

or comprehension

getproperties(object, properties) = 
    [getproperty(object, property) for property in properties]
getproperties(object, (:a,:c,:b))

? Quick benchmark:

@btime getproperties($Ref(object)[], (:a,:c,:b)) 

getproperties(object, properties) = 
    (getproperty(object, property) for property in properties)
@btime collect(getproperties($Ref(object)[], (:a,:c,:b))) 

getproperties(object, properties) = 
    [getproperty(object, property) for property in properties]
@btime getproperties($Ref(object)[], (:a,:c,:b))

yields

  293.243 ns (7 allocations: 288 bytes)
  319.383 ns (8 allocations: 400 bytes)
  242.857 ns (7 allocations: 288 bytes)
2 Likes

from the heart)

Why not just broadcasting getproperty:

getproperty.(object, (:a,:c,:b))
2 Likes

doesn’t work like that

Just define a broadcastable method:

Base.broadcastable(o::TestObject) = Ref(o)

and then you can do

julia> getproperty.(object, (:a,:c,:b))
(1, 3, 2)
4 Likes

Note also that in Julia 1.7 you can do property destructuring:

julia> (; a,c,b) = TestObject(1, 2, 3);

julia> a,c,b
(1, 3, 2)
4 Likes