Again, I'm mostly for generics being added to Go, because I've found occasion where they would be useful...
On Thursday, July 20, 2017 at 6:40:00 AM UTC-7, M P r a d e s wrote: > > Go could have least have parametric functions (ex : > > func Foo<T>(value T)T { /.../ } > > bar := Foo<int>(3) //types are verified at compile time, no need for > reflection or interface {} on any runtime trick. > > ). > To get at the value of adding generics, knowing what "Foo" is doing is important. Presumably, the function operates on "value" in some way. Can we say that it implements an interface? Then let's suppose the existence of an interface "X". I can currently rewrite your "Foo" function as: type X interface { Clone() X // documentation needed to clarify that the clone is really of the derived type implementing X. DoFoo() } func Foo(value X) X { result := value.Clone() result.DoFoo() return result } Now supposing I have a struct B, where *B implements "X", and is currently in variable "orig". When calling this, to reflect that the result of Foo is still of type *B, the following is required. fooClone:=(*B).(Foo(orig)) What I want to be able to write, and have *B as the type of "clone": fooClone:=Foo(orig) What we need the function signature to specify, then, is two pieces of information, that the parameter "value" is of the same type as its return, and that it implements interface "X". Also, my intuition suggests distinguishing generic types from concrete ones syntactically, so add an indication that's true. Perhaps try a few (+, ^, %). A bunch of options that all get at the same idea, using different characters and different approaches: func Foo(value T^->X) T^ func Foo(value T%:X) T% func Foo(value T+:X) T+ func Foo<T^->X>(value T^) T^ func Foo<T%->X>(value T%) T% func Foo<T+->X>(value T+) T+ where the "->" could really be anything syntactically appropriate, but what it means is "T" implements X. Again, not sure of the right syntax, and not sure this is required. In the "X" interface itself, we have a slightly different problem for the "Clone" method. We need someway to indicate "the concrete type of the thing". For that, we use the syntax indication of a generic type (^, %, or +, above) appended to something. "@" seems like a natural fit. That probably needs to look something like this: Clone() @^ Putting it all together, choosing my favorite representation from above: type X interface { Clone() @+ DoFoo() } func Foo(value T+:X) T+ { result := value.Clone() result.DoFoo() return result } Now, I can write what I wanted to write: fooClone := Foo(orig) There's a *completely separate question* as to whether the compiler generates code that is effectively of the form: fooClone := (*B).(Foo(orig)) I'm not sure I care about that. I'm more concerned about the correctness of the code. Eric. > > But talking about this is kind of useless until Go rids itself of its over > reliance on runtime features like reflection. I suspect Go reflection > capabilities are why the language stopped evolving significantly at first > place. String tags are another symptom of that "disease". > > It's possible to write the snippet above with reflection today > (reflect.MakeFunc) , it shouldn't be. > > > -- 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. For more options, visit https://groups.google.com/d/optout.