I am working on a Pipeline[T, U any] type which receives any number of T values and in turn emits U values. Pipelines are used to read from databases.
For instance, this code fetches the ages of 5 people under 50. int[] ages PeopleOrderedByName(Start[Person](). Map(func(p Person) int { return p.Age }). Filter(func(age int) bool { return age < 50 }). Slice(0, 5). AppendTo(&ages)) // Output: {49, 19, 25, 34, 42} fmt.Println(ages) Some notes about this code: 1. Start[Person]() returns a Pipeline[Person, Person] that emits each Person value it receives. 2. the Map method on Pipeline is parameterized. What Map returns depends on the return value of the mapper function passed in. In the example above, Map() returns a Pipeline[Person, int] 3. AppendTo(&ages) returns a Consumer[Person] which takes Person values without emitting anything. As a side effect, this Consumer[Person] appends the ages of people under 50 to the ages slice. 4. Even if there are millions of people in the database, this code will read just enough people to get 5 ages under 50. *5. This code won't work in 1.18 because methods in GO on a parameterized type like **Pipeline cannot be further parameterized, but in **this API, the Map() method has to be parameterized.* To get around this limitation, I revised my API to look like this: int[] ages PeopleOrderedByName( SendTo[Person, int]( Start(). Map(func(person interface{}) interface{} { return person.(Person).Age }). Filter(func(age interface{}) bool { return age.(int) < 50 }). Slice(0, 5), AppendTo(&ages)) // Output: {49, 19, 25, 34, 42} fmt.Println(ages) Notes about this API: 1. Pipeline is no longer a parameterized type. Pipeline instances receive interface{} values and emit interface{} values. 2. AppendTo(&ages) returns a Consumer[int] that appends all the values it receives to the ages slice. 3. SendTo[Person, int](....) returns a Consumer[Person] that applies a pipeline to the Person values it receives and then sends the emitted values to the Consumer[int] passed as a second value. *4. This API suffers all the disadvantages that generics aims to solve. The pipeline code is clunkier because values have to be constantly converted from interface{}, Problems with type mismatches become runtime errors instead of compile time errors, storing a Person value in an interface results in an extra memory allocation etc.* Is there a more elegant way around the limitation that methods on parameteried types can't be parameterized? -- 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/e180a4cd-0d5e-4b91-a238-b668206095acn%40googlegroups.com.