(All that said, if you're thinking in terms of multiple inputs and outputs you're missing the point. The output isn't a pair, it's one or the other, and that's really important. You need to be able to make invalid states unrepresentable, so a disjoint union is not just a pair)
"Building a backtracking facility in smalltalk without kernel support"[1]
Languages like Snobol, Prolog, and Icon were designed with backtracking facilities from the outset and these facilities are deeply intertwined with the implementation. Retrofitting a backtracking facility in a language that wasn't designed for it has never been achieved. We report on an experiment to retrofit Smalltalk with a backtracking facility. The facility is provided through a small number of primitives written in the language (no modifications to the kernel were made). The ability to do this is a direct result of the power provided by the objectification of contexts.
There's tons of other examples, for example various distributed objects mechanisms, my own Higher Order Messaging [2] the way Gemstone creates queries from procedural selection code etc.
"Smalltalk-76 had to provide a mechanism for passing unevaluated code. [Blocks/Closures] Since the Smalltalk-76 design had no experience to draw from, it was weak in several areas.[..]
One Problem which was discovered in the process of of supporting error recovery was that block contexts could not be restarted because they did not include their initial PC as part of their state. This was normally needed for looping , since all such code fragments ended with a branch back to the beginning. Happily, we were able to fix this by defining a new subclass."
So they were able to fix a bug in the language implementation by writing code in the language itself!
It seems the more experince people get with large team efforts the more they value Java and other well supported type safe languages.
I'm a perfect example myself as a person who used to think that a number of other languages would be better but after having to maintain my own (yep, not only someone elses bad code, but also my own precious code) in a number of languages I've come to really prefer Java.
I will say Joshua Bloch's Effective Java is something ever Java dev should have read at some point.
https://tahoe-lafs.org/~davidsarah/noether-friam4.pdf has a more concrete set of tradeoffs: starting from a small, highly symmetric core, you add more capabilities to the language but you break a symmetry each time. One of the levels in the rainbow is an OOP language, but that requires breaking enough symmetries that I wouldn't want to work in it if I could avoid it.
Yes. Yes. We know. You can write programs with OO. It's the dominant paradigm of the software industry. No one here saidthat OO is somehow ineffective, cannot abstract, or lacks cleverness.
Please for even comment section just put down the sword and let other folks with equally interesting approaches talk about their work.
Also I've been here for a number of years and I can never recall seeing anyone bashing FP. (Which is totally fine with me.)
Bashing Java and and general OO however is to be expected in any programming related thread here (a little tiring but understandable, I too have seen my share of bad OO code.)
Neither of this counts as proof but yes, this site comes off as extremely pro FP for me as well.
This is a great illustration of my point. If you place every differing viewpoint in one bucket and then take the sum, yeah it's gonna see overwhelming. In actuality, there are lots of factions with interesting viewpoints.
Well I'm guilty of that, even on this page ;-)
mpweiher's post that you replied to only mentions Smalltalk, Snobol, Prolog, and Icon, neither of which are FP languages AFAIK.
Furthermore IIRC the post only defends OO languages. I cannot read it in any way as an attack on FP languages and I've tried multiple times now.
That's like saying functional programming is the dominant paradigm, because Javascript has functions.
Pointing to prior art is a good and useful thing for a comment to do.
Common Lisp also isn't coming back despite having some amazing features. Let's both dry our tears and move on.
Mentioning something great that smalltalk is capable of isn't the same as saying everyone should use smalltalk. It's more saying - let's not forget some of the great stuff that existed in the past that the current crop of popular languages don't have.
Even this example where someone says something totally unrealted to OO, someone felt compelled to leap in and say something as unrelated as, "OO too! Here's a barely related OO project I found to be clever! Please don't forget about us."
Let me just remind you how this went:
Person A:
> The essence of FP is that if you apply a bit of cleverness and engineering, you can replace things that look like they would need custom language features
Person B: > Same for OOP, example from 1988:
No one even implied that this was exclusive! But certainly other folks have used the word "defense" for that post, perhaps not even realizing it. As if the existence of other paradigms somehow threatens the importance of OO.
Except that it isn't "a notable difference", more precisely (quoting the original):
"replace things that look like they would need custom language features, like multiple return or async, with libraries"
Replacing "things that look like they would need custom language features" with libraries is exactly the essence of Smalltalk.
"Talk small and carry a big class library"
It's even in the Design Principles Behind Smalltalk:
"A language must provide a means for classifying similar objects, and for adding new classes of objects on equal footing with the kernel classes of the system."
So either there is a claim that "hey this is a cool way of doing things", in which case "yeah, I agree, this other thing does that as well" is completely benign.
Or there is the claim "here is uniquely FP way of doing things", in which case the example of OO is a refutation.
Either way the response is appropriate.
Only in the example showed in the website, if you want to have progress reports/feedback on your happy path and keep it even if you go to the error path then having a multiple result/structure containing both results at the same time make sense.
Also, We're not taking about maybe types here. This article is demonstrating a specific library that composes a specific either type using F#'s computation expressions or custom operators.
Lots of people don't know what computation expressions are, nor are they familiar with the bind operator. They don't know why they'd use an either type instead of try/catch.
You can always reduce the number of words to say something, but you often sacrifice context and end up alienating people when you take too much for granted.
You also know what type the error will be. No need to derive a new class from `Error` and add custom functions to extract the data from your failure case, just pass the data along.
I've been writing a lot of Kotlin recently, and Kotlin doesn't have checked exceptions. This has led me to start migrating away from exceptions entirely because without checked exceptions it gets too hard to track what can fail, and how. I've been switching to an approach like the author's of using an `Either` (actually `Validated` from arrow-kt -- a special purpose `Either`) to have failures in my return values. I just have to be careful when calling library code to immediately translate exceptions into return values, but the entire stack in my own code has no exceptions (aside from unrecoverable errors).
It's not about avoiding the goto like behavior. It's about making you to know it exists and forcing you to handle it.
Rathet than throwing 5 calls deep, doing nothing until you empty your call stack, you must explicitly say "I know I'm part of a system that may error" at each step along the way.
That said, it's often preferred to use Either<Success,Error> because then you can try to explain what went wrong. A Maybe cascade failing can be pretty mysterious when you start to compose them, and you're deliberately creating something your optimizer will inline into an difficult-to-debug straight line of code.