Earlier quoted context omitted.
It has to be AI generated or at least edited right? The reliance on bulleted lists. The endless adjectives and declarations. ...but also the subtle... well not exactly errors, but facts I think are open to dispute? Such as: > Together, these tools make Go perfect for microservices, real-time systems, and high-throughput backends. Real-time systems?! I have never heard of anyone using Go for realtime systems because o…
I have never heard of anyone using Go for realtime systems because of its GC and preemptive scheduler. I don't know. I've seen "realtime" used quite often in a sort of colloquial sense, where it means something fairly different from "hard realtime system" as an embedded systems person might use the term. I think there's a pretty large base of people who use "realtime" to mean something that others might call "near re…
Go beyond Goroutines: introducing the Reactive paradigm
31–40 of 43 posts
Re: Go beyond Goroutines: introducing the Reactive paradigm
#32The supposedly bad example is perfectly readable to anyone familiar with Go. A bit of refactoring into first class functions, and you'd have an easy to read, idiomatic, easy to test, well typed code base with obvious places to adjust useful behaviors like concurrency limits. Meanwhile the samber/ro example is incomplete (Subscribe(...)?), and the source includes some weird stuff: https://github.com/samber/ro/blob/22b…
I like how he kept "tabs" (and display it as 9 spaces) to make it as ugly as possible for the bad example, then proceed to use 4 spaces for the other examples.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#33Earlier quoted context omitted.
I like how he kept "tabs" (and display it as 9 spaces) to make it as ugly as possible for the bad example, then proceed to use 4 spaces for the other examples.
Tabs are the recommended indentation method for Go code. It is interesting that they switched after the first example, though.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#34The supposedly bad example is perfectly readable to anyone familiar with Go. A bit of refactoring into first class functions, and you'd have an easy to read, idiomatic, easy to test, well typed code base with obvious places to adjust useful behaviors like concurrency limits. Meanwhile the samber/ro example is incomplete (Subscribe(...)?), and the source includes some weird stuff: https://github.com/samber/ro/blob/22b…
I like how he kept "tabs" (and display it as 9 spaces) to make it as ugly as possible for the bad example, then proceed to use 4 spaces for the other examples.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#35Re: Go beyond Goroutines: introducing the Reactive paradigm
#36Earlier quoted context omitted.
it's used extensively in java and it would be my first choice when starting a java project. I don't think I'd use it in Go though.
reactive is on the decline in the java world post-loom (virtual threads) and should be nobody's first choice. writing plain old imperative code is vastly simpler to write / debug / reason about. Brian Goetz even went as far as saying loom is going to kill reactive entirely: https://www.youtube.com/watch?v=9si7gK94gLo&t=1165s
So yes, in this particular case, most of the usages of RxJava, Reactive Streams and particularly Spring Reactor is just there because programmers wanted pretty simple composition of asynchronous operations (particularly API calls) and all the other alternatives were worse: threads were too expensive (as Brian Goetz mentions), but Java did have asynchronous I/O since Java 1.4 and proactor-style scheduling (CompletableFuture) since Java 8. You could use CompletableFutures to do everything with asynchronous I/O, but this was just too messy. So a lot of programmers started using Reactive framework, since this was the most ergonomic solution they had (unless they wanted to introduce Kotlin).
That's why you'd mostly see Mono types if you look at a typical reactive Spring WebFlux project. These Mono/Single monads are essentially CompletableFutures with better ergonomics. I don't mean to say that hot and cold multi-value observables were used at all, but in many cases the operator chaining was pretty simple: gathering multiple inputs, mapping, reducing, potentially splitting. Most of this logic is easier to do with normal control flow when you've got proper coroutines.
But that's not all what reactive frameworks can give you. The cases when I'd choose a reactive solution over plain coroutines are few and pretty niche: to be honest, I've only reached to a reactive 3 or 4 times in my career. But they do exist:
1. Some reactive operators are trivially mapped to loops or classic collection operators (map/reduce/filter/flatMap/groupBy/distinct...). But everything that's time-bound, is more complicated to implement in a simple loop, and the result is far less readable. Think about sample or debounce for instance.
2. Complex operation chains do exist and implementing them as a reactive pattern makes the logic far easier to test and reason about. I've had a case where I need to implement a multi-step resource fetching logic, where an index is fetched first, and then resources are fetched based on the index and periodically refreshed with some added jitter to avoid a thundering herd effect, as well as retries with exponential backoff and predictable update interval ranges which is NOT affected by the retries (in other words: no, you can't just put a delay in a loop). My first implementation tried to model that with pure coroutines and it was a disaster. My second implementation was RxJava, which was quite decent, and then Kotlin Flow came out, which was a breeze.
3. I'm not sure if we should call this "Reactive" (since it's not the classic observable), but hot and cached single values (like StateFlow in Kotlin) are extremely useful for many UI paradigms. I found myself reaching to StateFlow extensively when I was doing Android programming (which I didn't do a lot of!).
In short, I strongly disagree with Brian Goetz that Functional Reactive Programming is transitional. I think he's seeing this issue from a very Java-centric perspective, where probably over 90% of the usage we've seen for it was transitional, but that's not all that FRP was all about. FRP will probably lose its status a serious contender for a general tool for expressing asynchronous I/O logic, and that's fine. It was never designed to be that. But let's keep in mind that there are other languages than Java in the world. Most programming languages support some concept of coroutines that are not bound to OS kernel threads nowadays, and FRP is still very much alive.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#37The supposedly bad example is perfectly readable to anyone familiar with Go. A bit of refactoring into first class functions, and you'd have an easy to read, idiomatic, easy to test, well typed code base with obvious places to adjust useful behaviors like concurrency limits. Meanwhile the samber/ro example is incomplete (Subscribe(...)?), and the source includes some weird stuff: https://github.com/samber/ro/blob/22b…
I like how he kept "tabs" (and display it as 9 spaces) to make it as ugly as possible for the bad example, then proceed to use 4 spaces for the other examples.
You can see this your self if you edit the markup in your browser’s inspector and add `contenteditable` attribute to the surrounding
, then navigate down a line... it will jump forward just by slightly less then a column per indent level.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#38Earlier quoted context omitted.
reactive is on the decline in the java world post-loom (virtual threads) and should be nobody's first choice. writing plain old imperative code is vastly simpler to write / debug / reason about. Brian Goetz even went as far as saying loom is going to kill reactive entirely: https://www.youtube.com/watch?v=9si7gK94gLo&t=1165s
I think there is an issue where reactive frameworks are massively overused in languages that have (or had) weak concurrency patterns. This was true for a while in JavaScript (before async/await became universally supported), but it's especially endemic in the Java world, especially the corners of it which refused to use Kotlin. So yes, in this particular case, most of the usages of RxJava, Reactive Streams and partic…
Yes, a transitional technology for the _Java Language/Platform_ post Loom. He never said anything about Functional Reactive Programming in general.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#39My understanding was that Go intentionally avoided patterns like this to improve readability.
Sometimes it feels like that Go mistakes readability for comprehendability. Sure, I can read every single line of Go I've ever read. But can I comprehend the bigger picture? Can I understand why? Isn't the actual meat buried under piles of non-abstraction? This is precisely the premise for their library: I don't have the mental context to fit all the boilerplate in, nor do I have the brainpower to sift through it. Su…
var result := []string{}
for i = 0; i
return resultI more readable than this code:
return items
.filter { it
The argument is that everybody understand what the loop does, it's just a stupid loop. Bring back an an Algol 68, Pascal or C programmer from the 70s and they all understand what a for loop is. But my second example requires you to learn about filter and map and closures and implicit parameters like 'it'.Of course, once you do understand these very complicated concepts, the code above is far more readable: it clearly states WHAT the program does (filtering all values below the threshold and converting them to string) rather than HOW it does that (which nobody cares about). "readability" here is only counted from the narrow perspective of an imperative programmer who is not familiar with functional declarative data processing.
I feel the same about the "ro" examples in the OP. I don't particularly like that ro takes (mostly because Go forces its hand, I assume), like having to put everything in an explicit pipe, but I find the example far more readable than the pure Go example which combines loops, channels and WaitGroups. That's far worse than the loop example I gave in this reply, to be honest, and I really don't know why people say this example is readable. I guess you can optimize it a little, but I always found both channel and WaitGroups waitable, unreadable and error prone. They are only "readable" in narrow perverted sense that has somehow become prevalent in the Go community, where "readability" is redefined to mean: no closures, no immutable values, no generics, no type safety and certainly nothing that smells like FP.
Re: Go beyond Goroutines: introducing the Reactive paradigm
#40Earlier quoted context omitted.
I think there is an issue where reactive frameworks are massively overused in languages that have (or had) weak concurrency patterns. This was true for a while in JavaScript (before async/await became universally supported), but it's especially endemic in the Java world, especially the corners of it which refused to use Kotlin. So yes, in this particular case, most of the usages of RxJava, Reactive Streams and partic…
> In short, I strongly disagree with Brian Goetz that Functional Reactive Programming is transitional. Yes, a transitional technology for the _Java Language/Platform_ post Loom. He never said anything about Functional Reactive Programming in general.
Maybe this is what Brian Goetz meant to say, but this is not what he said.