Multi-Paradigm Languages(oreilly.com)
oreilly.com
Multi-Paradigm Languages
https://www.oreilly.com/radar/multi-paradigm-languages/
45 comments
Having read Christopher Alexander before encountering GoF, I am a little sympathetic to the GoF.
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.
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.
Yeah, I appreciate their intent, but I think they made a mistake in thinking they were near the end of programming history. They really thought they were zeroing in on a lasting, almost ideal style, but it turned out to be a style that was quickly made obsolete by changing languages, programming concepts, processes, and architectures. Also, in software, you're designing for the machine and for other programmers, and it's a lot easier to discover how well a software design performs for machines and colleagues than it is to discover how an architectural design performs for a family, a company, or a society. I do appreciate the intent, but it's hard to see why someone would still be sticking with the design patterns concept twenty years later.
I think you're not looking deeply enough. Sure, there are problems when people don't know a language or a paradigm well enough to be comfortable or productive in it. But once they know two paradigms well enough, the "pure vs impure" question becomes a real question in its own right, rather than a cover for "I don't know one of them well enough".
But once they know two paradigms well enough, the "pure vs impure" question becomes a real question in its own right
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.
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.
One fantastic multi-paradigm-from-the-start language that often gets missed out is Mozart/Oz - http://mozart2.org . This language is used in the awesome book "Concepts, Techniques, and Models of Computer Programming" by Peter van Roy and Seif Haridi - https://www.info.ucl.ac.be/~pvr/book.html
Mozart/Oz is so underrated. It's a shame it never took off.
AliceML was also an interesting hybrid of Oz + SML.
AliceML was also an interesting hybrid of Oz + SML.
> Mozart/Oz is so underrated. It's a shame it never took off.
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.
[1] http://www.vendian.org/oz/wiki/index.cgi?VirtualManual
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.
[1] http://www.vendian.org/oz/wiki/index.cgi?VirtualManual
Just wanted to add my recommendation for Concepts, Techniques, and Models of Computer Programming" by Peter van Roy and Seif Haridi.
This is an amazingly thorough, comprehensive and erudite work. Highly recommended.
This is an amazingly thorough, comprehensive and erudite work. Highly recommended.
This is a great and mind expanding book/System. However since Mozart/Oz does not seem to be used that much in the "real world", i think it maybe worthwhile to investigate application of the same ideas to a mix of Erlang and C/C++.
Although it's nominally about C++, this book looks at the design issues for selecting among paradigms based on application characteristics. IE it generalizes to other languages capable of supporting multiple paradigms.
https://www.amazon.com/Multi-Paradigm-Design-C-James-Coplien...
https://www.amazon.com/Multi-Paradigm-Design-C-James-Coplien...
I worked at a company where they had to fire some of Scala programmers. The people who were fired were functional purists, whereas a bunch of the team were coming from Java and (understandably) wrote Scala as if it were just more terse Java (very Kotlin-esque).
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.
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've been a Scala programmer for close to ten years now, and I've been shocked at how blithely people will 1) unilaterally commit their coworkers to enormous learning curves, without regard for the consequences, and 2) use crucial projects as personal learning opportunities, again without regard for the consequences. Partly it's self-indulgence, partly it's machismo, partly it's a sincere desire to build the best thing possible, but whatever the motivation, it can cause a huge mess. People need to feel responsible for leaving a certain ratio of polished, mature
code to beginner, learning code, even though that means that (gasp!) they can't live in a permanent state of learning big new things.
IMHO scala projects require company’s wide enforced coding styles. Otherwise one group will try writing it as Haskell while the other will run off with Java crap that is simply not needed in scala
That's right. And actually, once you stick to one of them, Scala is an amazing and productive language, better than Kotlin and Java are and will probably ever be. But mixing the two styles does not work out.
I agree. Vanilla OO/functional Scala, focused on immutability and functional idioms, but without effect systems and type classes, can be a really beautiful, simple, expressive, highly productive way to develop software. I'm neck deep in FP Scala now (the cats ecosystem with cats-effect) and hoping I eventually come to feel the same way about it.
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'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'm neck deep in FP Scala now (the cats ecosystem with cats-effect) and hoping I eventually come to feel the same way about it.
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.
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.
We're thinking about ZIO. It looks really nice, but we have applications built on a lot of different frameworks already, and I'm worried about how we can rein in our tendency to always add more technologies and never reduce and consolidate.
Yeah, I can see that. The good thing is that you can replace cats.effect with ZIO quite easy - not so much the other way around once you use ZIO specific features though. It's a tough decision...
I agree but it goes both ways. Bolting some over-engineered and mostly unnecessary Java pattern or framework/di on top of scala does not simplify things either. Why lifhtbend had to make guice standard in their play framework is beyond me
A superficial article, not good enough.
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".
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".
Another option is DSL[0]. It takes some time to create a new language and other team members have to learn it, but long-term efficiency will be out of the roof!
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.
[0] https://en.wikipedia.org/wiki/Domain-specific_language
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.
[0] https://en.wikipedia.org/wiki/Domain-specific_language
It does exist and it's called Racket [1] and language-oriented programming. You can write prolog-like languages [2], or Haskell-like [3], or even C-like languages [4].
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
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
I used Racket at some point alongside SICP ~10y ago. I always considered it being a pure educational/experimental/research language.
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.
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.
In my opinion, a promising avenue for programming would be DSLs with restricted semantics + SAT/SMT solving to deliver lightweight formal methods.
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.
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.
Yes! There is some work being done in this space already; by the incredible people at North-Eastern. One of the more interesting parts of this problem is what you do at the /boundaries/ of the different languages with differing semantics such that you don't accidentally introduce bad lemmas.
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 .
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 .
I think I know some of these papers, but could you please point me to some of the references you have mentioned?
Of course — this paper talks about the mechanism which Racket explores to keep the boundary safe [1]. This
paper [2] elaborates on some of the performance challenges. 'Shallow typing' by Ben Greenman et al.
is available only by video [3] and slideshow form [4]. Finally, there's a really interesting paper which came out
this year which uses a verifier to remove the some of the runtime cost [5] of sound gradual typing.
[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...
[5] https://arxiv.org/abs/2007.12630
[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...
[5] https://arxiv.org/abs/2007.12630
Thank you so much!
This is the reason why I am exited about GraalVM and its support for polyglot programming[1] (via the Truffle framework).
[1] https://www.graalvm.org/reference-manual/polyglot-programmin...
[1] https://www.graalvm.org/reference-manual/polyglot-programmin...
A path already crossed by both IBM i and z OS, and the CLR.
So while it is great that Java eco-system is going down the same path, we should not forget those that went there first.
So while it is great that Java eco-system is going down the same path, we should not forget those that went there first.
I can think of two examples, only one of which is me being a smartass.
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.
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.
Let me chime in also here. Besides racket, which is a great choice when liking lisp syntax and dynamically typed code, there is also Java which has python-like syntax and allows for amazing DSLs that are typesafe but still easy to use. Probably the best language for DSLs in production, especially if typesafety is important.
I think SWIG (the Simplified Wrapper and Interface Generator, www.swig.org) may be what you're looking for. It can create interface code for calling language X from language Y. I'm not sure it covers all the most popular 20 languages, but it covers a lot.
The platform you're describing is the way I use bash (understood that you're asking for a little more integration than just exec/fork/spawn).
This article has me torn. On the one hand, I always use multiparadigm languages at work, and have always preferred a pragmatic, "best tool for the job" approach.
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.
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.
With Java I've seen an increasing problem with programming style in large projects because of it's kitchen sink support of so many paradigms.
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.
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.
> With Java I've seen an increasing problem with programming style in large projects because of it's kitchen sink support of so many paradigms.
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”.
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”.
Some of those FP concepts, transposed into a class-based OOP context, like closures and algorithms over data structures, where already present in Smalltalk-80 actually.
It’s pretty easy to go full procedural with static where classes function only as a name space. Also, I’ve worked in code bases that were a Frankenstein mixture of deeply nested inheritance hierarchies mixed with attempts to be fully functional mixed with C code written in Java. So I stand by my statement.
A little surprised Swift and Kotlin aren’t mentioned. Both expressly support FP and OOP approaches (although some of Swift’s FP-enabling features like protocols look more familiar in OOP contexts, similar to the common misconception that TypeScript is primarily designed for OOP).
Raku (formerly Perl6) is multi-paradigm.
"metalanguage does not exist"
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.