hi there, I was trying out the generics proposal https://github.com/golang/go/issues/15292, via the "Go2 playground": https://ccbrown.github.io/wasm-go-playground/experimental/generics
the thing I am trying to solve is, basically, a generic way to: - pass a function with any number of parameters and a single return value - "bind" that function to a slice of pointers to values (that will point to, e.g., values extracted from a db) - create a closure that returns the value from evaluating the function with the bound paramaters. basically, I am defining this interface: type Formula interface { Vars() []string Bind(ptrs []interface{}) error Func() interface{} } that people would be able (in Go-1) to implement like so: type FormF64F32ToI64 struct { vars []string arg0 *float64 arg1 *float32 fct func(x1 float64, x2 float32) int64 } func (f *FormF64F32ToI64) Vars() []string { return f.vars } func (f *FormF64F32ToI64) Bind(ptrs []interface{}) error { // check number of args elided. f.arg0 = ptrs[0].(*float64) f.arg1 = ptrs[1].(*float32) return nil } func (f *FormF64F32ToI64) Func() interface{} { return func() int64 { return f.fct(*f.arg0, *f.arg1) } } so some "framework/library" code can work in terms of this Formula interface and let clients register formulae (with a set of column names to read from the database) in a relatively type-safe way, and quite performant one too (you pay the price of the type-assert once when you retrieve the function closure): usr, err := db.Formula(&FormF64F32ToI64{ names: []string{"col1", "col42"}, fct: func(x1 float64, x2 float32) int64 { return int64(x1) + int64(x2) }, }) check(err) fct := usr.Func().(func () int64) err = db.IterRows(func(tx Tx)error { fmt.Printf("row[%d]: %d\n", tx.ID, fct()) }) check(err) implementing the Formula interface from a given func is a pretty mechanical job. right now, I am doing it with a little go/types-based command. today, I tried to do the same with the generics proposal: ===== package main type Formula interface { Names() []string Bind(args []interface{}) error Func() interface{} } type Form2 (type T1,T2,U) struct { names []string arg1 *T1 arg2 *T2 fct func(t1 T1, t2 T2) U } func (f *Form2(T1,T2,U)) Func() interface{} { return func() U { return f.fct(*f.arg1, *f.arg2) } } func (f *Form2(T1,T2,U)) Names() []string { return f.names } func (f *Form2(T1,T2,U)) Bind(args []interface{}) error { if len(args) != 2 { panic("invalid number of arguments") } f.arg1 = args[0].(*T1) f.arg2 = args[1].(*T2) return nil } var ( _ Formula = (*Form2(float64,float32,int64))(nil) ) func main() { arg1 := 42.0 arg2 := float32(42) args := []interface{}{&arg1, &arg2} form := &Form2(float64,float32,int64){ names: []string{"f64", "data"}, fct: func(x1 float64, x2 float32) int64 { return int64(x1) + int64(x2) }, } err := form.Bind(args) if err != nil { panic(err) } fct := form.Func().(func() int64) println("fct=",fct()) } ==== it's definitely an improvement: I "just" have to write the generics code for functions with a given arity (say, 0, 1, ... 5) w/o having to pre-generate all the functions I (or my users) may need for all combinations of (types x arity). it's not completely satisfactory, though, as: - it's not "as general" a solution as what one could come up with, say, std::function (from C++), where you "just" have to give a function pointer and it handles everything else for you (arity, in this case) - there's probably the issue of "generic type argument" collision: how to differentiate (in the current scheme) between 'func(x1 float64) (float64, int64)' and 'func(x1, x2 float64) int64'? (this could perhaps be addressed w/ a different way of describing my Form2 generic type.) perhaps there's a better way of doing this? (perhaps even w/ "just" Go1) it'd be great to just have to write: var f Formula = &Form(func(float64,float64)int64){ names: names, fct: func(x1,x2 float64) float32 { return float32(x1+x2) }, } and have everything instantiated and implemented correctly. thoughts? cheers, -s PS: here's the direct link to the Go+Generics playground of the code above: https://ccbrown.github.io/wasm-go-playground/experimental/generics/#A4Qwxg1iDmCmAEBbEBLAdgKAwem/AGoQFzwAqAFigM7zXyXTkA2AnvLAB7CwBOKisNABcQTAHTwAIgHs0AciHsusMIrDSePFULSwqNDfCoiARiiYohLMVivd4AMQ2IArkxC1hvAGbgEAbwx4YPgAORABKgAKAEp4AG0AXWM+NGggkIAhdAATKJAeaBok9CEfP38AXzjeHg0M4IcXNDBYzzKeXzBYKoxK2xZ7Jx5EACZ4KLsEUgBGABpSUbmAVTiUl1V4QJD4NAi9BOShVPSdgugZ+AAqWYb4c/Gb0bvvTe9m1qFL2bn4IXHFnFln0sO8WhNvNdhmMoj9FisYnEmi02qVyt0qlsMABILRCFw8NDwMGtIFY7G42D4wnEsSvIRRK7eMTnebXZkPGI4/r9DAkiFQ5yjWHzeGrOLhSJtJIpdDQLbwPEEonMvaReD9flRSFXaHCuFLcXwbJoPLnYqJNGdCrVdiaQzbEIoSFMQT5QpUOIAQgAvPBxo6dsFQGgUK0AEToABuohQOV2LkQJl48GkkPOicEQio4a5O36Ow5hUufvN8QADIkxIzZnmQkXoONSx74jMqzXRnXgkqaaGmCCMDGeBM7gB9RzONweP2MvXapjSEBCABsABY5t4F0uAMxLUprxFRPtcrl8j5IVBoNqBbGs+BEP2r0Zics4h73v2bxdCXdRJ9c28PQ/Q4rS6HpKn8AAyVlfmgwpRn6bEcW8ZxgMgucvyXNcNy3H892EA8bx2NU9BIGVjjlfxw28Ndw1+cMciXEBw0qOYcULVQSBJKIOEuTCV3XeAOHGfjdzifdVwVHsiQkniZjiABqdo1x4zsNTY7FENqYCUJGMQTTND0AOdO1h19XZzAVEMwyiWo4kQ5DNgfYlnDEZFSWrbjxII1cAOAVIhCYK9qNUH06PpWIuX6IA== -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/GjwPzdvak9pzi3b0gLgbIYT95QzRCiRV1fuUG6SpD2tYeVQEPLMinw2BBIRLcB0pdLpIFJl984i1QBWFsgeBPs2ZZBGFIZud6GOYJmwCEao%3D%40sbinet.org.