-
Notifications
You must be signed in to change notification settings - Fork 3k
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
buckets and splitBy operators #6388
buckets and splitBy operators #6388
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial comments. Will review it properly, later. Also, for PRs that change the public API, you will need to use npm run api_guardian:update
.
* default hash function converts the values into numbers, if they are not | ||
* already. | ||
*/ | ||
hashFn?: (value: T) => number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I'm not a fan of abbreviations. I'd prefer hasher
, instead, but this can be bikeshedded later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i also just picked this up from somewhere, bikeshed away ;)
9467c97
to
6ad4057
Compare
in regards to naming: is edit: |
I think it could probably be a single operator - |
personally, i dont like merging them into a single operator. too overloaded from user & dev perspective. but that's just my feeling. |
TBH, I was not planning on bringing |
So looking over this, at first blush. const buckets = (count) => groupBy((value, i) => i % count)
// or
const buckets = ({ count, hasher }) => groupBy((value, i) => hasher(value, i) % count);
// or
const splitBy = (predicate) => groupBy(predicate); Am I off-base? What am I missing? |
To be clear @backbone87 ... this is awesome work! And I really appreciate it. However, we're going to be on the hook to support this API long-term, so I want to be sure we're doing the right thing. |
Another thing to consider... And const source = interval(1000);
const result = source.pipe(buckets(3));
const capturedBucketSubs = [];
const outerSubs = result.subscribe(bucket => {
capturedBucketSubs.push(bucket.subscribe(console.log));
});
// unsubbing outer first shouldn't kill existing inners
setTimeout(() => {
outerSubs.unsubscribe();
}, 5000);
setTimeout(() => {
for (const subs of capturedBucketSubs) {
subs.unsubscribe();
}
}, 10000); I'm willing to agree this behavior is SUPER debatable, but there it is, and that's how groupBy has worked for years, for better or worse. Here's an example of that behavior with |
Sorry, too, @cartant, if I'm just springing this on you. When we talked about this at the core team meeting, I guess I was thinking |
edit: on buckets vs groupBy: |
@benlesh As I mentioned above, I was planning on ignoring FWIW, I kinda agree with you on dumping this in favour of When I added dogsAndCats.pipe(
groupBy(isDog),
mergeMap(grouped => grouped.key
? /* Observable<Dog> */ grouped.pipe(tap(() => console.log('woof')))
: /* Observable<Cat> */ grouped.pipe(tap(() => console.log('meow')))
) I don't know that there is any advantage in using
Rather, I think dogsAndCats.pipe(
splitBy(isDog),
mergeMap(([dog$, cat$])=> merge(
dog$.pipe(tap(() => console.log('woof'))),
cat$.pipe(tap(() => console.log('meow')))
)
) TL/DR: I don't see a compelling case for |
@cartant maybe if we get everything in a monorepo, |
@backbone87 I see your point, that you get the array of observables ahead of time. I'll still need to think about it. Because, in practice, I'm not sure about the advantage that gives. Still thinking about this one. |
no hard feelings here on my side, a little bit of disappointment, but I can handle this, if it doesn't fit, then leave this out. personally, I have used partition only on very few occasions, but when I did, I definitely wasn't happy with its behavior as it is right now and would have preferred the splitBy behavior. also, these situations could have most likely also been solved with groupBy. |
to bring in an example where the splitBy behavior may be useful: pipe(
splitMap(2, ([nextParsed, nextUnreadable]) => (value) => {
if (value === null) {
return nextParsed(value);
}
try {
nextParsed(JSON.parse(value));
} catch (e) {
nextUnreadable(new UnreadableMessage(value, e));
}
}),
mergeMap(([parsed, unreadable]) => {
return parsed.pipe(
splitMap(2, ([nextValidated, nextUnreadable]) => (value) => {
if (validate(value)) {
nextValidated(value);
} else {
nextUnreadable(new UnreadableMessage(value, validate.errors));
}
}),
mergeMap(([validated, unreadable2]) => of([validated, merge(unreadable, unreadable2)])),
);
}),
); idk that still looks way too convoluted |
After discussing this PR in the Core Team meeting, I'm so sorry to say that I don't think we're going to go ahead with it at this time, and we should probably close the related issue. That issue, TMK, was filed at a time when Thank you so much for your hard work, @backbone87, we all really do appreciate it. I'm sorry that this isn't something we can merge into core for now. Especially given that it was just trying to implement something that was requested by a core team member years ago. Thank you again, @backbone87, and I hope this doesn't put you off from further contributions. |
hm ok, no problem. i suspected it.
|
I'm interested in a way to replicate the |
-spec.ts
tests file covering the canonical corner cases, with marble diagram testsdocs_app/content/guide/operators.md
in a category of operatorsDescription:
Introduces 2 new operators
buckets
andsplitBy
.buckets
uses a hash function to partition values across multiple multicasted (hot) observables. This behaves similar togroupBy
, but the groups are known immediately.splitBy
is the special case ofbuckets
where the count of buckets is 2. This is similar topartition
, but has a usage ergonomy more similar togroupBy
.implementation is based upon
bucketBy
andsplitBy
inrxjs-etc
by @cartantRelated issue (if exists): #3807 #4419 #5731