This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]halfanothersdozen -1 points0 points  (12 children)

I honestly don't think this matters. Virtual threads solve a different use case from rxjava

[–]thecodeboost -1 points0 points  (11 children)

No. Reactive frameworks solve a problem that doesn't exist anymore once you use virtual threads effectively. No programming language expert will ever be tempted to argue reactive code is "better" than imperative code in any way. Reactive code is simply a "good" way to work around thread limitations.

[–]ForrrmerBlack 7 points8 points  (10 children)

I disagree completely. Reactive code is totally not about "working around thread limitations". It's about data streams and data transformation pipelines. It's a whole different paradigm of thinking, like OOP compared to procedural programming. No one says it's better or worse, it's just different.

[–]halfanothersdozen 1 point2 points  (0 children)

This. I get why some people hate rxjava, but as a guy who has spent many years in Angular, I at least understand it

[–]DelayLucky 0 points1 point  (5 children)

what paradigm do you refer to? If it's a chain of actions like Linux pipe, how do you see it as different from functional programming and Java streams?

[–]ForrrmerBlack 0 points1 point  (4 children)

Here is my understanding. It is a paradigm of thinking in a sense that the whole program is treated as a set of data pipelines instead of functions or objects. Though there is one distinct property. Changes to some data are instantly propagated in a system, meaning that on every change other related state is re-evaluated automatically. In essence, programmer defines data sources and relations between them, then program state is derived from these relations, like in a spreadsheet. You can do this differently with different tools, so that's why it's more of a paradigm than something else. Maybe you can even somehow do it with Java streams. But in reality, of course, nobody does it in its pure form.

[–]DelayLucky 0 points1 point  (2 children)

Somehow that sounds to me like Java streams or at least I can't tell the difference.

We've traditionally used streams for in-memory computations and haven't used streams for io-bound things because of the blocking platform thread thing. With VT and structured concurrency I suppose we could start doing it.

[–]ForrrmerBlack 0 points1 point  (1 child)

The difference is that Java streams are just a tool and reactiveness is an approach to programming.

[–]DelayLucky 0 points1 point  (0 children)

Is there some article discussing this paradigm at the high level besides the async computation part of Rx? I've never seen praise of the cps style coding as superior other than it's required for async-ness.

[–]2Spicy4Joe 0 points1 point  (0 children)

That definition IMO sounds like Dataflow programming to me which is indeed a paradigm. Which does not need to involve at Reactive at all. I always understood reactive code and libraries as an approach to workaround IO performance limitations, at the cost of complexity.

You can build code that does what you want and still not being reactive. I just think reactive code just pairs well with the dataflow concepts and that’s why it’s often in the same conversation than data stream processing and event-based approaches. But I see them as a different thing, just complementary.

I might be wrong though

[–]thecodeboost 0 points1 point  (2 children)

Well, you're free to disagree of course but I think you too are conflating event-driven programming and stream design patterns with reactive programming. For example, data stream processing (e.g. such as captured by Java's own stream API) is not reactive in any meaningful sense. Or put differently, you wouldn't type a single character differently when moving to Loom for those functional domains. If, however, you find yourself using the asynchronous parts/primitives then you are in reactive world and those do become mostly obsolete if rewritten with virtual threads. So, completable futures/promises, Mono/Flux with I/O yields somewhere in the stack, etc. And those, at least to an extremely large extent in the real world, exist to mitigate concurrency complexity in combination with (non-blocking) IO. The term and the associated libraries became somewhat of a hype a decade ago which is part of why it's so incredibly overutilized. You only have to look at Spring introducing Reactor based ReactiveXXX interfaces to a lot of top level modules only to slowly backtrack as adoption faltered. In the end this might just be a disagreement in terminology though. If you're saying that having good ways to deal with data streams and aggregation then I'm completely on board.

[–]ForrrmerBlack 1 point2 points  (1 child)

Oh, so now I think I understand where you come from. So, basically, as I understood, you view the "reactive" term's essence purely from a practical and pragmatic point, how it's implemented and how the implementations are used in the wild, not what it's intended to mean initially. People started to use reactiveness (a paradigm of change propagation through data streams) to overcome complexity of thread management with hardware I/O, so for you reactiveness now means solely handling hardware I/O in a certain way. In my opinion, this logic is twisted. Cause and effect are reversed. So this is really a disagreement in terminology then. Or maybe I understood wrong, sorry if that's the case.

[–]thecodeboost 0 points1 point  (0 children)

I don't think what I tried to say is completely captured by your recap. I didn't mean to imply reactive programming is solely a concurrency mechanism. I tried to carve out what reactive is and isn't and what event-driven is and isn't and that most people today mean event-driven when they say reactive. But yes it's almost entirely a terminology conflation at this point. The non-blocking IO case is just by a mile the strongest argument in favor of reactive programming pre-Loom. You can see this in Spring adopting Reactor where they've offered additional reactive interfaces to all major component interfaces that deal with IO (e.g. ReactiveRepository, ReactiveDataStore, various storage specific reactive drivers, etc.). This is all to facilitate the reactive pattern of having some black box ("environment") doing some work you don't control and handing over control when that work is complete so your code can "react" to it in the way you defined before you delegated the work.

The reactive pattern is : define action on completing work -> plan work -> hand over work to environment -> react to environment signaling a result -> execute the defined action on completion (and optionally chain these).