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

pipeline-equals assignment #125

Open
towc opened this issue May 30, 2018 · 4 comments
Open

pipeline-equals assignment #125

towc opened this issue May 30, 2018 · 4 comments
Labels
follow-on proposal Discussion about a future follow-on proposal

Comments

@towc
Copy link

towc commented May 30, 2018

In the proposal I saw no mention of something like variable |>= fn as a clean shorthand for variable = fn(variable), so I thought I'd bring it up so it can be added to the spec with this proposal, and doesn't bite us later.

You might want to discourage it as JS is going more and more functional, but if so, it would be nice to have that written in the proposal as well

@ajcrites
Copy link

ajcrites commented Jun 2, 2018

I think that this could be useful for cases where you want to pass properties through the pipeline. This would solve a similar problem to async/await by allowing you to use operator results in the same scope as other operators in the pipeline.

A Promises example:

I think it's easier to exemplify with a working Promises example. This is a real world scenario: You need to read some items from storage, set some configuration, and make a network request -- all async operations.

getItemsAsync().then(items =>
  setConfigAsync(items).then(
    () => httpGet(items),
  ),
);

This creates more rightward drift in the code. Alternatively you could use let:

let oitems;
getItemsAsync().then(items => {
  oitems = items;
  return setConfigAsync(items);
}).then(() => httpGet(oitems));

async/await solves this problem by putting all of the operators in the same scope. Imagine we're in an async function...

const items = await getItemsAsync();
await setConfigAsync(items);
return httpGet(items);

I think this is much easier to reason about, and it doesn't require "carrying values around," if that makes sense.

Applying to the pipeline

Imagine an Observable chain that does the same operations:

getItems$().pipe(
  mergeMap(items => setConfig$(items).pipe(
    mergeMap(() => httpGet$(items)),
  ),
);

... alternatively ...

getItems$().pipe(
  mergeMap(items => setConfig$(items), (_, items) => items),
  mergeMap(httpGet$),
);

If the chain gets longer, the carrying around of items becomes more cumbersome.

You can see complaints about this here: ReactiveX/RxJava#2931 and quite a few other places.

Solution using the pipeline and assignment

If you can do assignment in the pipeline this problem is solved by keeping the values in the same scope as the other operators:

// `of` is used here to kick off the Observable chain
of(1)
const items |>= mergeMap(() => getItems$()),
            |> mergeMap(() => setConfig$(items)),
            |> mergeMap(() => httpGet$(items)),

This syntax isn't perfect, but I think the general idea is good.

@littledan
Copy link
Member

I'd like to leave this idea for a follow-on proposal, and leave the initial proposal simpler and minimal. What do you think?

@elycruz
Copy link

elycruz commented Jun 24, 2018

@ajcrites Hey, I see your reasoning for wanting this though for your scenario

getItemsAsync().then(items =>
  setConfigAsync(items).then(
    () => httpGet(items),
  ),
);

which is the same as:

getItemsAsync()
  .then(setConfigAsync)
  .then(httpGet);

The composition, in my opinion, would be better composed as 'something that happens outside of an observable' which can then be called from an 'observable':

const someProcess = async () => 
  await getItemsAsync() 
    |> x => (await setConfigAsync(x), x) // I know, just for our example
    |> x => await httpGet(x)
;

no (in other words, you wouldn't even need observable chains involved, for process, in javascript)?

// Updated example above

Same as example above but without sequences:

const 
  someProcess = 
    async () => getItemsAsync()
        .then(x =>  setConfigAsync(x).then(() => httpGet(x))
;

@elycruz
Copy link

elycruz commented Jun 24, 2018

@ajcrites @towc 👍 for participation/effort 👍 Also @ajcrites The someProcess I show above is 'point-free' and allows the process to be easily composed with other function calls of a simliar structure (async functions etc.). Also no mutability (in example) 👍

@tabatkins tabatkins added the follow-on proposal Discussion about a future follow-on proposal label Sep 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
follow-on proposal Discussion about a future follow-on proposal
Projects
None yet
Development

No branches or pull requests

5 participants