Cysharp / R3

The new future of dotnet/reactive and UniRx.
MIT License
1.72k stars 70 forks source link

Add ScanSelect(Func<TSource, TSource, TResult>) (TState, Func<TSource, TSource, TState, TResult>) #164

Closed kochounoyume closed 3 months ago

kochounoyume commented 4 months ago

This was implemented to address a use case I was faced with.

I could not think of a way to implement similar functionality with an existing combination of operators.

Therefore, I am proposing this because I think it would be useful if it were available.

Of course, I leave it up to you to decide if you want to incorporate it into this repository.

notes Some existing variables have been renamed for consistency in the source code.

neuecc commented 4 months ago

Thank you. Can you explain the differences and advantages compared to Scan, along with specific use cases? It would be difficult to include this as-is. Also, passing the default as the initial accumulation to the selector seems suboptimal.

kochounoyume commented 4 months ago

Thanks for the feedback. And I apologize for the lack of explanation.

What I want to achieve with this "ScanSelect" is, in essence, to return the value of the previous subscription and the current subscription at the same time. Currently, "Scan" can only handle values that can be calculated with the previous subscription value and the current subscription value, or with those values associated with a seed. If one tries to obtain or calculate more complex structured data from those values, the implementation will inevitably be less than clean.

The use case I have experienced is an implementation related scroll views. The scroll view fires an event when scrolling and notifies the current scroll percentage by means of a subscription (using the R3 library). Unfortunately, this scroll view is a legacy one that does not have a function to disable display outside the view range, so you will need to implement such a function yourself. In such cases, "ScanSelect" would be quite useful. For example, it makes no sense to find the amount of scrolling that has been moved by "Scan" for example. To find the elements to be displayed, it is necessary to calculate with the previous and current subscription values, respectively, and compare the group of elements to be displayed obtained to find new elements to be generated or discarded. To meet these demands, it was necessary to create an operator that could inject at least these values.

The inclusion of a "Select" element is a little extra for expressiveness and versatility.

neuecc commented 3 months ago

From the perspective of needing the previous value, can't we use Pairwise? If an initial value is needed, I think it's fine to additionally use Prepend.

kochounoyume commented 3 months ago

Indeed, I hadn't thought of the combination of Pairwise and Prepend. I would like to experiment with that a bit. Once I do, I think I'll put this pull request in draft status and close it depending on how it behaves. Thanks for the advice!

kochounoyume commented 3 months ago

I just checked the Pairwise and Prepend pairs. These are great operators! Thanks for your patience with my little problem. I'll close this pull-link here.