Broadcasting getproperty over an empty vector of structs does return Any[] instead of a concrete type

I’m not sure if this is a bug, or if I am missing something:

struct X
    a::String
end

struct Y
    a::String
    b::Vector{String}
end

x = X[]
y = Y[]

Broadcasting getproperty(..., :a) over x and y does return String[] for x but Any[] for y. Should it not return String[] in both cases?

1 Like

See this comment in particular, but some of the surrounding discussion as well.

The short answer is that broadcasting getproperty/getfield often doesn’t constant-propagate the field like you want. You get the desired result for x because there’s only one property that could be accessed, but for y it can’t tell whether you’re accessing the a or b property (which each have a different type, hence the uncertain type info).

You’ll get the proper result if you make a “getter” function dedicated to that particular field and broadcast or map that. I recommend you try something like map(z -> z.a, y) or (z -> z.a).(y), or map/broadcast a dedicated accessor function that you make if it’s worth making such a function (both of my recommendations do this, but only using a throw-away anonymous function).

2 Likes

Consider using map instead.

julia> f(y) = getproperty.(y, :a)
f (generic function with 1 method)

julia> f(y)
Any[]

julia> f(y) = map(s->s.a, y)
f (generic function with 1 method)

julia> f(y)
String[]

julia> f(y) = map(s->getproperty(s, :a), y)
f (generic function with 1 method)

julia> f(y)
String[]