-
Notifications
You must be signed in to change notification settings - Fork 33
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
Fold processing stage #66
Comments
About About tuples and pairs, Java does not provide anything, and yes it's a pain. Implementing pair is easy. Implementing tuples is a bit more complicated because of the lack of type (or you need Now I'm not sure if the stream spec is the right place to define such utility classes but I don't have a strong opinion. For sure these classes are very useful when dealing with streaming / messaging. |
Forgot to mention our favorite topic: naming. the
For the record, fold seems to be the most used word in the mathematical world: https://en.wikipedia.org/wiki/Fold_(higher-order_function) I would go for About the variant, here are the candidates:
Another detail is whether or not the seed value is emitted in the downstream stream. |
Definitely agree that streams is not the right place to define tuples. With regards to naming - we also must consider, currently we have Akka Streams does this by making all folds that are terminal defined as constructors of Maybe this is a non-issue, When you mention whether the seed value is emited in the downstream stream, do you mean whether the next element is separated out from the state and emitted? This is where tuples are useful, with a tuple (assuming language sugar with <R, S> PublisherBuilder<R> fold(S initial, BiFunction<S, ? super T, (S, R)> accumulator); Without a tuple, we'd have to create a type just for it: class FoldResult<S, R> {
private final S state;
private final R result;
...
}
<R, S> PublisherBuilder<R> fold(S initial, BiFunction<S, ? super T, FoldResult<S, R>> accumulator); Another possibility is to do what <R, S> PublisherBuilder<R> fold(S initial, BiFunction<S, ? super T, S> accumulator, Function<S, R> finisher); I don't really think that's necessary, since the |
Naming: I believe the Emission: If you look at the scan method from RX (especially the marble picture), the operator emits the seed as the first value. The second value is computed using the accumulator. My question is whether we want the same behavior and emits the seed value or wait until we get the first value and call the accumulator. |
What about making it explicit which methods are terminal? E.g. prefixing them with |
My primary concern with differentiation between terminal and intermediate operations is actually about future proofing. If we add fold today as an intermediate operation, but in future we decide we want a fold terminal operation, what can we do? Likewise, currently we have reduce as a terminal operation, what happens if there's a good reason in future to also have a reduce intermediate operation? Anyway, I'm not sure that it necessarily has to be addressed, just worth having a discussion about. That RX Java behaviour is very weird. Reactor does the same. I don't know what the use case for that would be. Eg, calculate a running average, initial value is irrelevant. Emit an event on change of value, initial value is irrelevant. Calculate a running total, no one cares about zero, it's uninteresting. |
I have an opposite opinion - for a person that doesn't use streams daily such as me, it's very hard to remember the names of terminal operations. I often end up going through all the stream/observable methods just to find something that might do what I want and the only differentiator between terminal and non-terminal operations is the method return type and it's very hard to filter them out, the IDE or Javadocs don't help there |
Other potential prefixes for terminal stages:
I'm not too keen on any of the above, thoughts? |
As the goal is to be as close as possible from the Java Stream API, using |
I think a folding processing stage would be good. There are a number of use cases that I've come up with, particularly in IoT scenarios.
Let's say you have an IoT device that every few seconds sends the status of a door, ie, whether the door is opened or closed. You want to convert this status to an action, ie, a message should only be sent when the door changes from opened to closed, or vice versa, so that you can then do further processing down the stream without overwhelming your system with these status messages every few seconds. This is what it might look like:
Another use case might be that you have a temperature sensor, and you want to output a running average. This can be done in a very similar way to above.
One of the things that makes this not so nice is Java doesn't have a concept of tuples - typically when you do a fold, you want to fold into a tuple of your state, and an event that you want to output, and then a subsequent map will just emit the event and drop the state. But without tuple support in Java, you have to either do like the above, hack it using arrays, or create a new class just to hold your tuple. Of course, there are libraries out there that provide tuples, eg Akka provides
Pair
, though it's still cumbersome without any sort of syntactic sugaring around it provided by the language.The text was updated successfully, but these errors were encountered: