Reputation: 33
I am not sure if I'm trying to exceed the limits of what Go will allow, but here is the context:
I have type called Map
with a hefty number of helpful member functions, such as Interpolate
, Add
, and Clear
. I also have a struct type, Layered
, that contains several Map
s.
type Map [][]float64
func (m Map) Interpolate(min, max float64) { ... }
func (m Map) Add(val float64) { ... }
func (m Map) Clear() { ... }
type Layered struct {
data []Map
}
I would like to add a member function to Layered
that accepts any member function of Map
as an argument, and then calls it on all of its contained Map
s. Something along the lines of:
func (l Layered) MapCall(callMe func(Map)) {
for _, m := range l.data {
callMe(m)
}
}
This partially works, but only for member functions of Map
that take no additional arguments, such as Clear
. Is it at all possible to accept any member function of Map
as an argument (along with its potential parameters in the form of an ...interface{}
), and then call the function, with its correct parameters, on all of the member Map
s in a Layered
? Something like this, for example:
func (l Layered) MapCall(callMe func(Map, ...interface{}), params ...interface{}) {
for _, m := range l.data {
callMe(m, params...)
}
}
Upvotes: 0
Views: 1208
Reputation: 573
You may want to be more functional than try to use interfaces.
I will provide an example using your Interpolate
method.
You can start by defining a helper function for generating the operation:
func InterpolateOp(min, max float64) func(Map) {
return func(m Map) {
m.Interpolate(min, max)
}
}
Another name that would match your MapCall
function better is MapInterpolate
.
Then, when using MapCall
or creating lists of operations, you can use the same type you were using previously, namely func(Map)
:
var l Layered
...
l.MapCall(InterpolateOp(2, 4))
The key to this solution is that the data is bound to the closure that makes up the function, which solves the original problem: not enough data to call the appropriate functions.
In your case, if there are so many methods that this is not worth doing, then you may look into code generation, since it is repetitive and easy. That is outside the scope of this question.
See also: https://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions
Upvotes: 1