Comments (14)
Generics proposal is now accepted.
This will be interesting. 😇
from go-linq.
If getting rid of type-agnostic From()
and leaving the FromXxx, that’s worth pursuing.
from go-linq.
Hi, i made myself an early and naive one here https://github.com/szmcdull/glinq. Would you have a try?
from go-linq.
@ahmetb Have you considered using Facilitators to mitigate the limitation of having no generic parameterized methods? See https://rakyll.org/generics-facilititators/
from go-linq.
So I tried to imitate what From
..Where
..Select
.. sort of thing would work.
Each Where/Select/... would have different type parameters:
type Array[K any] []K
func (a Array[K]) Print[V any](v V) {
for _, i := range a {
fmt.Printf("%v-%v\n",i,v)
}
}
However this is not supported by design. https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#methods-may-not-take-additional-type-arguments
from go-linq.
Based on my last experimentation, Go generics unfortunately isn't advanced enough to support this by design.
But I also encourage others to try Select().Order() where each method takes a generic type and returns another generic type processed further down the chain.
from go-linq.
@StevenACoffman sadly the main problem with Go generics is the chaining won't work the way we currently have in this library. If you look at @szmcdull's glinq
library, the chaining goes Any(Where(FromSlice(...
(versus what we have today is FromSlice().Where().Any()
. As method chaining becomes sophisticated, nested method approach is hard to read and reason about.
I am yet to see a feasible way to achieve the chaining approach we currently have with Go generics.
In the meanwhile, other libraries like lo
that aren't fully linq (but offers small helpers) has emerged in the ecosystem. But the reason I insist not going the Go generics route is that I want to preserve the existing way of chaining LINQ methods as this library strives to be close to .NET LINQ in terms of look and feel.
from go-linq.
Here is another try, more complex and playing around with the From
function for slices, maps, channels and strings. We need to have a constructor for each type: https://gotipplay.golang.org/p/wUTln-sObFy
from go-linq.
Here is my first try and keeping the go-linq original design: https://go2goplay.golang.org/p/gH50GCy32S7
Thoughts?
package main
import (
"fmt"
)
type Query(type T) struct {
Iterate func() func() (T, bool)
}
func From(type T)(source []T) Query(T) {
len := len(source)
return Query(T){
Iterate: func() func() (T, bool) {
index := 0
return func() (item T, ok bool) {
ok = index < len
if ok {
item = source[index]
index++
}
return
}
},
}
}
func (q Query(T)) Where(predicate func(T) bool) Query(T) {
return Query(T){
Iterate: func() func() (T, bool) {
next := q.Iterate()
return func() (item T, ok bool) {
for item, ok = next(); ok; item, ok = next() {
if predicate(item) {
return
}
}
return
}
},
}
}
func (q Query(T)) ToSlice() (r []T) {
next := q.Iterate()
for item, ok := next(); ok; item, ok = next() {
r = append(r, item)
}
return
}
func main() {
sliceInt := []int{1, 2, 3, 4, 5}
sliceInt = From(sliceInt).
Where(func(i int) bool {
return i < 4
}).ToSlice()
fmt.Println("Int:", sliceInt)
sliceStr := []string{"a", "b", "c", "d", "e"}
sliceStr = From(sliceStr).
Where(func(i string) bool {
return i < "d"
}).ToSlice()
fmt.Println("Str:", sliceStr)
}
from go-linq.
That’s a good start. I didn’t think a whole lot about this. But in this example basically seems the whole chain works only on the initial type provided. What if we say From(ints) but the result of the chain returns []string?
If there was a way to instruct certain methods such as ForEach<int,string>(ints) that could return []string that would be nice. I suspect that doesn’t exist. So that makes me wonder if we need to integrate with generics at all.
from go-linq.
What if we say From(ints) but the result of the chain returns []string?
The proposed way will probably be a breaking change in the library. All projection
methods that convert a type to another should be declared as a constructor function passing the source query as a parameter. In .NET, the extension methods
make the syntax easier.
https://go2goplay.golang.org/p/CFQH-AKIfCU
package main
import (
"fmt"
"strconv"
)
type Query(type T) struct {
Iterate func() func() (T, bool)
}
func From(type TSource)(source []TSource) Query(TSource) {
len := len(source)
return Query(TSource){
Iterate: func() func() (TSource, bool) {
index := 0
return func() (item TSource, ok bool) {
ok = index < len
if ok {
item = source[index]
index++
}
return
}
},
}
}
func Select(type TSource, TResult)(q Query(TSource), selector func(TSource) TResult) Query(TResult) {
return Query(TResult){
Iterate: func() func() (TResult, bool) {
next := q.Iterate()
return func() (item TResult, ok bool) {
var it TSource
it, ok = next()
if ok {
item = selector(it)
}
return
}
},
}
}
func (q Query(T)) Where(predicate func(T) bool) Query(T) {
return Query(T){
Iterate: func() func() (T, bool) {
next := q.Iterate()
return func() (item T, ok bool) {
for item, ok = next(); ok; item, ok = next() {
if predicate(item) {
return
}
}
return
}
},
}
}
func (q Query(T)) ToSlice() (r []T) {
next := q.Iterate()
for item, ok := next(); ok; item, ok = next() {
r = append(r, item)
}
return
}
func main() {
sliceStr := []int{1, 2, 3, 4, 5}
sliceInt := Select(
From(sliceStr).Where(func(i int) bool { return i < 4 }),
strconv.Itoa,
).ToSlice()
fmt.Println("Select:", sliceInt)
}
from go-linq.
That's excellent. So we can do that after all I guess. Which part of the code you're referring to by "constructor"?
from go-linq.
What I meant was, this kind of implementation would not be possible:
func From(source interface{}) Query {
src := reflect.ValueOf(source)
switch src.Kind() {
case reflect.Slice, reflect.Array:
return FromSlice(...)
case reflect.Map:
return FromMap(...)
case reflect.String:
return FromString(...)
case reflect.Chan:
return FromChannel(...)
default:
return FromIterable(...)
}
}
We would need to use the specific "Query constructor" function in each particular type.
from go-linq.
@ahmetb are there any plans to still try to implement this lib with generics since go 1.18 beta has been released?
from go-linq.
Related Issues (20)
- Append方法优化
- "GroupBy has better performance than GroupByT" is written on the document,why?
- ToChannelT release? HOT 2
- why union.go file doesn't have func UnionBy like the func IntersectBy in intersect.go
- Why `ToSlice` need a custom grow strategy instead of the standard library? HOT 1
- runtime error: hash of unhashable type map[string]interface {} HOT 9
- Unit test ExampleOrderedQuery_ThenByDescending fails on golang-1.19.2 HOT 6
- sort result is unexpected HOT 1
- How to implement the full join function of SQL
- new generic functions type HOT 1
- 转换错误 HOT 1
- I expect the data queried using gorm to be converted using go-linq HOT 1
- bug in WhereIndexed HOT 7
- Article comparing performance of go-linq vs others HOT 4
- gopkg.in/ahmetb/go-linq.v3: gopkg.in/ahmetb/[email protected]: parsing go.mod: module declares its path as: github.com/ahmetb/go-linq/v3 but was required as: gopkg.in/ahmetb/go-linq.v3 HOT 5
- how about add parameter timeout for FromChannelT?
- Is it safe to copy in multiple concurrency HOT 2
- How to implement complex SQL functions HOT 5
- PLINQ support HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-linq.