struct Car
color::String
model::String
gears::Int
end
and I have another struct
struct CarGroup
cars::Vector{Car}
end
I would like all the functions called on Car to be applied to CarGroup in this way:
function color(c::Car)
return c.color
end
function color(cg::CarGroup)
return map(cg.cars) do c
color(c)
end
end
Is this thing even possible with standard language? I imagine that I can define a macro that does and add it to all the functions of interest… but I would much prefer some magic function of the type:
function f(cg::CarGroup, args...; kwargs...)
map(c->f(c, args...;kwargs...), cg,cars)
end
No. The syntax for it does exist, but we’re deliberately prevented from defining one method for arbitrary callables because it silently interferes with other functions’ dispatch e.g. we really don’t want print(::CarGroup) calls to be affected:
julia> function (f::Function)(cg::CarGroup, args...; kwargs...)
map(c->f(c, args...;kwargs...), cg,cars)
end
ERROR: cannot add methods to builtin function `Function`
Stacktrace:
[1] top-level scope
@ REPL[6]:1
julia> function (f::Any)(cg::CarGroup, args...; kwargs...)
map(c->f(c, args...;kwargs...), cg,cars)
end
ERROR: cannot add methods to builtin function `Any`
Stacktrace:
[1] top-level scope
@ REPL[7]:1
julia> function (f::F)(cg::CarGroup, args...; kwargs...) where F
map(c->f(c, args...;kwargs...), cg,cars)
end
ERROR: function type in method definition is not a type
Stacktrace:
[1] top-level scope
@ REPL[5]:1
Best we can do is metaprogramming for select callables (see karei’s @eval loop), or embrace a higher order function that takes input callables. map(color, cg.cars) is already fairly terse, the only possible improvement is a custom higher order function that accesses the cars field for us like carmap(color, cg), which doesn’t save much writing.
Also note that it generally doesn’t really make sense to forward “all” functions in this manner.
For example, a recolor(car::Car)::Car function generalized to CarGroup should probably return CarGroup back, not a Vector{Car} like map would do.