Anton Zhernov
Anton Zhernov

Reputation: 41

Writing a generic binder in Go

Consider the following function -- a binder of the second argument.

func bindSecond(value interface{}, f func(a interface{}, b interface{})) func (c interface{}) {
    return func(arg interface{}) {
        f(arg, value)
    }
}

Consider a function

func f(x int, y int) {}

When trying to use it as a parameter in binder, go compiler says:

cannot use f (type func(int, int)) as type func(interface {}, interface {}) in argument to bindSecond.

Could you please suggest me the proper way of implementing binders in go (golang)?

Upvotes: 1

Views: 454

Answers (2)

tomasz
tomasz

Reputation: 13072

I see what you're trying to do, some templates, right? But this is not going to work this way. Your f func(a interface{}, b interface{}) argument is not an interface, so it must be of the matching type. You could achieve what you want by passing f interface{} and then manipulate it with reflect package.

Some naive example:

package main

import (
    "fmt"
    "reflect"
)

func bindSecond(value interface{}, f interface{}) func(c interface{}) {
    return func(arg interface{}) {
        reflect.ValueOf(f).Call([]reflect.Value{reflect.ValueOf(arg), reflect.ValueOf(value)})
    }
}

func main() {
    sum := func(x int, y int) { fmt.Println(x + y) }
    inc := bindSecond(1, sum)
    inc(10)
}

// Prints 11

Doable, but not very pretty. And panics in runtime if anything unexpected happens, for example f is not callable and doesn't take exactly two arguments. Or you pass a wrong type to inc. Complier won't help you anymore.

Upvotes: 4

Staven
Staven

Reputation: 3165

Replace interface{} with int and it will work.

Or, more to the point, try to find a solution to your original problem using the features Go provides, instead of trying to force a solution from a different paradigm.

Upvotes: 4

Related Questions