ReactiveX / RxGo

Reactive Extensions for the Go language.
MIT License
4.95k stars 337 forks source link

Support for generics #250

Open tdakkota opened 4 years ago

tdakkota commented 4 years ago

Experimental go2go translator is published! https://blog.golang.org/generics-next-step

teivah commented 4 years ago

Hey @tdakkota, Thanks for creating the issue. For information, I started to work on it on the generics branch but I didn't finish yet. It's really a heavy change and so far the compiler is sometimes panicking without providing useful information so it's not simple. Anyone who's willing to give it a try can start working from generics (or your own branch, whatever works).

czras commented 2 years ago

With the upcoming 1.18 go release would this issue pick up some steam?

manisenkov commented 2 years ago

I think because of lacking of parameterized methods in the current state of generics it would be impossible to migrate this project without major change of API.

aak1247 commented 2 years ago

@manisenkov But still helpful

evanmoran commented 2 years ago

I suspect if generics improve the API we'd very much be fine with a breaking API change. Any thoughts on if the current generics Go feature would be enough to make things easier to use?

manisenkov commented 2 years ago

RxGo is pretty much based on fluent interface (observable.Filter(...).Map(...)) and without type parameters in methods it wouldn't be possible to implement.

The one way is to switch to non-fluent API but it would be not as easy to read

Map(Filter(observable, filterFn), mapFn)

or

ob1 := Filter(observable, filterFn)
ob2 := Map(ob1, filterFn)

(here is an issue for adding type parameters)

simake2017 commented 2 years ago

when can finish it

ianldgs commented 2 years ago

Would it be helpful to take inspiration from RxJs and use a pipe function with operators also as functions?

Pipe(
  observable,
  Filter(fn),
  Map(fn),
  Reduce(fn)
)
manisenkov commented 2 years ago

Would it be helpful to take inspiration from RxJs and use a pipe function with operators also as functions?

Pipe(
  observable,
  Filter(fn),
  Map(fn),
  Reduce(fn)
)

I thought about it, but generics in Go doesn't support variadic number of type arguments. Some kind of solution would be if you have multiple variance for Pipe function for different number of arguments

Pipe2(
  observable,
  Filter(fn)
)

Pipe3(
  observable,
  Filter(fn),
  Map(fn),
)

Pipe4(
  observable,
  Filter(fn),
  Map(fn),
  Reduce(fn),
)

// etc...
ianldgs commented 2 years ago

An example of what the above could look like: https://go.dev/play/p/AJwmCH2iIA-

plastikfan commented 6 months ago

If anyone is interested, I have created a new version of RxGO - lorax (RxGo with generics) that is implemented using generics, but maintains the existing interface (ie it is still fluent). It is still under construction, but most of it is implemented and working. At some point, I intend to work through the item list defined here in RxGO and fix those issues, if there is interest. There are some caveats though:

The heart of the new generic based funcationality was to introduce a new opaque field defined as any to Item[T]:

    Item[T any] struct {
        V    T
        E    error
        aux  any
        disc enums.ItemDiscriminator
    }

All channels are strongly typed to Item. Whenever an auxilary value needs to be send thru the channel, an auxilary item can be created (Num in the example below), eg the Range factory iterates using an int based index, which needs to be sent via a channel. Since the channel can only send Item[T], the Range function creates an aux value (via newRangeIterable), carrying the integer value:

        for idx := i.start; idx <= i.start+i.count-1; idx++ {
            select {
            case <-ctx.Done():
                return
            case next <- Num[T](idx):
            }
        }

This is only meant as a stop gap project, just waiting for rxgo V3, but since that doesnt seem to be forth-coming, this stop gap looks to becoming more permanent than I intended.