Multi-Paradigm Languages
oreilly.com
oreilly.com
Most people won't remember, but there was a time in the 1990s when there were a lot of professional programmers who were not comfortable with OO. In a codebase, you'd get fights between people who embraced classes and utilized dynamic dispatch and people who didn't see the point of those things and were able to be extremely productive without them. Now there are a ton of professional programmers who are not comfortable with FP, coexisting in the profession with programmers who have fallen in love with type classes and use them habitually to solve every problem. It's a massively unjust cop-out to tell the former that they need to "reject purity," as if it's a moral flaw they need to fix. It's a long process of learning new skills and concepts, during which they will not be performing as accustomed at their job. People who balk at that are not just narrow-minded. People who focus on present productivity rather than future productivity are often the people who are getting the most work done, and it's important for an organization to figure out a path forward for the entire team before letting a new paradigm loose in the codebase. Moreover, it's legitimate to ask if the short-term consequences will be balanced out by long-term gains.
Also, as a response to the article trying to mix design patterns into the argument, if people want to make design patterns a thing, the idea needs a complete relaunch. Convince me that they're worth the effort. In my twenty years of experience working with other programmers, programmers who know design patterns are not better programmers than those who don't. I don't feel any less capable having 99% forgotten them. Most importantly, younger programmers who never bothered with them are just as good at structuring code as those of us who worked through the GoF book during our formative years. My opinion: just let it go.
Yeah... "once they know," which is after their time and effort has been spent and the opportunity cost has been incurred. Investing time and effort in learning something is, indeed, an effective way of finding out if the investment is worth it, but since you find out after the fact, it can't inform the decision to make the investment or not.
Also, somebody who was hired for their knowledge of one paradigm and is currently working productively in it, as is frequently the case, does not need "cover" for not knowing a different paradigm.
IMHO, the idea of patterns addresses two things: 1 - attacking the "haystack/spaghetti" that most large systems tended to result in, by providing a vocabulary or standard set of metaphors that can be used to encourage rather than discourage some good practices; and 2 - provide a common meta-vocabulary for discussing design (sometimes those "discussions" are between a long gone programmer and someone that encounters the code later).
Of course what we got instead was fetishism and towers of factory classes emitting envelopes resulting code that was diffuse, incomprehensible, and that focused on things other than the actual problem at hand. Despite my theoretical sympathies I stay far far away from the GoF.
This reminds me of the Agile movement: not that bad an idea for a technical management consulting team trying to solve a customer's tactical problem. But outside that domain only some bits and pieces make sense, and, depending on the domain, not always the same bits and pieces. Again: fetishism took over.
https://www.amazon.com/Multi-Paradigm-Design-C-James-Coplien...
This is an amazingly thorough, comprehensive and erudite work. Highly recommended.
AliceML was also an interesting hybrid of Oz + SML.
The documentation was a major barrier. More so than any other language (trying for public adoption) that I can immediately think of. A textbook-expensive dead-tree book as onboarding path. With the usual pattern of commercial thing reducing incentive to create accessible thing, without fully meeting the need for same. And online documentation that was fragmented and poorly integrated. So "looking up" a topic would involve groveling over a pile of documents, and lecture notes and such, searching out pieces of the puzzle, and pulling them together yourself. So much niftiness, so inaccessibly documented. :/ I once massaged together a distributed table of contents[1] (long since link rotted), which might give a feel for it. Part of the problem was M/Oz was at heart a teaching and academic effort - think of early Racket.
One of the hardest things about capturing history (and perhaps a fruitful way to teach it?) is the "wait, they wat?!!?". Picking up a language now, with expectations of how language and ecosystem are documented, and HN kibitzing on "the landing page should be improved by ...", reflects a big cultural learning process on how to do this well. Mozart/Oz, didn't.
Long story short, the third or forth time they were caught rewriting perfectly adequate and correct code simply because it wasn't embracing all of Scala's functional constructs, they were warned. Next time, they were canned.
I'm very sad about the Java OO extremists and the Scala functional extremists finding common cause in denying the possibility of moderate, limited use of Scala's power. Programming that way is head and shoulders above Java, and I've yet to see FP Scala match it for productivity (again, hoping and working, so fingers crossed.)
I think if you want to experience a similar feeling, you should look at ZIO instead.
It makes things so much easier compared to cats-effect by being less abstract and more direct, but still works with the cats type-classes. Really recommended for the functional side of Scala.
Better read this oldie but a goodie: Multi-Paradigm Design for C++ by James Coplien.
It is an oldie only in the sense that we have learnt new techniques on using the "template sub-language" within C++ in even more interesting ways like meta-programming etc. since then. With "Modern C++" more features have been introduced to increase the footprint of "design expression space".
Also, I think it would be nice, If there was a platform(maybe it exists?), which would connect let's say top 20 languages and it would be super easy to call function/block of code from other languages. Programmers just pick up the right language for the specific part of project.
You can even write BNF directly [5] and you can /call/ these constructs across different languages. Racket makes it /easy/ to play with semantics and syntax. You can feasibly write a language in an afternoon, to solve 1 specific problem.
[1] https://racket-lang.org/ [2] https://docs.racket-lang.org/datalog/datalog.html?q=datalog [3] https://github.com/lexi-lambda/hackett [4] https://docs.racket-lang.org/profj/ [5] https://beautifulracket.com/appendix/why-lop-why-racket.html
While this is likely a primary focus of Racket, it seems to be there is a ton to be gained from diving deeper into it, so thank you for these resources.
So, instead of programming in Turing-complete languages, one creates many specialized DSLs with just enough expressiveness. And, in parallel, some automated formal methods. The combination of a DSL and SAT/SMT makes this feasible, which contrasts with automated theorem proving on Turing-complete languages.
Racket seems like a good platform to do this.
There are a few published papers which study the boundary between dynamic and static type-systems, but the hope was to extend it into gradual-typing between different type-systems .
[1] https://www.cs.utah.edu/plt/publications/oopsla12-stff.pdf
[2] https://www2.ccs.neu.edu/racket/pubs/popl16-tfgnvf.pdf
[3] https://www.youtube.com/watch?v=A4AA8nweYAg
[4] https://www.ccs.neu.edu/~types/resources/talks/g-rcon-2020.p...
Emacs has a feature called org-mode Babel that lets you write scripts where you pipe the output from a block in one language to a block in any other language, but I don't think you could write a sizeable app this way.
The slightly more smart-alecky answer is the command line. I work in node, and it's trivial to call an external program and then operate on the output. There's nothing stopping you from writing a program that is a single function in the language of your choice and calling it wherever you want.
[1] https://www.graalvm.org/reference-manual/polyglot-programmin...
So while it is great that Java eco-system is going down the same path, we should not forget those that went there first.
On the other hand, I am starting to believe that, in truth, there are no multi-paradigm languages. Only imperative languages with bells and whistles. Because what matters isn't how you can use the language, it's how you do use the language. With the peculiar recent exception of Scala, multi-paradigm languages seem to always tend toward a mushy, homogeneous, imperative style whose most noteworthy feature is just how imperative it is. Even with all the classes, higher-order functions, and declarative DSLs sprinkled on top, the overall shape always ends up being overwhelmingly imperative. It takes more than a dollop of meringue to turn apple pie into key lime pie.
I didn't really start thinking this way until more recently, when I started looking outside of the mainstream and paying more attention to explicitly single-paradigm languages. I think maybe it's a bit like how McDonald's, A&W, Burger King, Hardee's, etc. all seem completely interchangeable if you don't spend a lot of time eating at them.
In addition to code readability it also effects code reviews because many cases come done to taste and it's difficult to build any type of consensus.
Java is pretty much the purest classic class-based OOP language of all industrially-significant languages. It has constructs inspired by those from other paradigms, especially FP, transposed into a class-based OOP context, but it's pretty much the last language I’d point it as suffering (or benefiting) from “support of so many paradigms”.