Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple operators for Pipe #227

Open
NoelAbrahams opened this issue Jan 28, 2024 · 4 comments
Open

Support multiple operators for Pipe #227

NoelAbrahams opened this issue Jan 28, 2024 · 4 comments

Comments

@NoelAbrahams
Copy link

Hi — brilliant library

Simple question: I would like to do the following:

mystream
    .pipe(
       flyd.filter(value => value !== 'foo'),
       flyd.skip(1),
       flyd.dropRepeats()
    )
    .map((value) => {
        console.log(value);
    });

Instead of

mystream
    .pipe(flyd.filter(value => value !== 'foo'))
    .pipe(flyd.skip(1))
    .pipe(flyd.dropRepeats())
    .map((value) => {
        console.log(value);
    });

Basically to avoid repeating .pipe as it is much cleaner.

I've seen some discussion here: #137

I'm assuming this pattern for pipe is somehow contrary to the design of flyd?

Thanks

@nordfjord
Copy link
Collaborator

I'm assuming this pattern for pipe is somehow contrary to the design of flyd?

IIRC the reason we went for a single function passed to pipe was because we didn't want to introduce the complicated TS required to type such a pipe function.

Ultimately pipe is a pretty generic thing, have you considered using something like remeda's pipe?

R.pipe(
    mystream,
    flyd.filter(value => value !== 'foo'),
    flyd.skip(1),
    flyd.dropRepeats(),
    flyd.map(console.log)
)

@NoelAbrahams
Copy link
Author

It will be nice to have this supported by the flyd lib. I've had a look at the API of a bunch of other similar libraries but I really like the fact that you have gone with pipe (which many other's don't seem to have).

There's nothing terribly wrong with chaining multiple pipe calls, but in the land of FRP these small deviations can grate, something explained quite well in this article on FRP.

Happy to help with the TS bits if needed.

@nordfjord
Copy link
Collaborator

I would hesitate to change it if it's only for stylistic preference. As mentioned, pipe is a pretty generic function that you can easily implement outside any library and can then use with any of your types.

const pipe = (x, f, ...fs) => fs.reduce((x, f) => f(x), f(x))

@NoelAbrahams
Copy link
Author

NoelAbrahams commented Apr 6, 2024

I've added the following to the lib locally:

Code

    function operator_pipe(...fns) {
        return fns.reduce((x, f) => f(x), this); 
    }

Typing

pipe<R>(op: OperatorFunction<T, R>): Stream<R>;
pipe<A1, V>(op0: OperatorFunction<T, A1>, op1: OperatorFunction<A1, V>): Stream<V>;
pipe<A1, A2, V>(op0: OperatorFunction<T, A1>, op1: OperatorFunction<A1, A2>, op2: OperatorFunction<A2, V>): Stream<V>;
pipe<A1, A2, A3, V>(
    op0: OperatorFunction<T, A1>,
    op1: OperatorFunction<A1, A2>,
    op2: OperatorFunction<A2, A3>,
    op3: OperatorFunction<A3, V>,
): Stream<V>;
pipe<A1, A2, A3, A4, V>(
    op0: OperatorFunction<T, A1>,
    op1: OperatorFunction<A1, A2>,
    op2: OperatorFunction<A2, A3>,
    op3: OperatorFunction<A3, A4>,
    op4: OperatorFunction<A4, V>,
): Stream<V>;

Where

    interface UnaryFunction<T, R> {
        (source: T): R;
    }
    interface OperatorFunction<T, R> extends UnaryFunction<Stream<T>, Stream<R>> {}

This works for me. Happy to close the issue if it's not going to be supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants