On multi-paradigm programming languages
I enjoy learning more about new programming languages and see how they can be used to produce high quality software. I tend to like languages that are opinionated about one should use them, especially if they have sensible defaults and if they have some peculiary feature.
Scala and F# are languages that are functional first but that also support the object oriented paradigm. They both sacrifice ‘purity’ for a better interoperability with, respectively, Java and C#, the main languages of their runtime environment. For how much I like opinionated languages, I think this is a sensible and pragmatic trade-off. This lets developers choose the right tool for the job and makes it possible to use the new languages for new projects on legacy codebases.
All the advantages I mentioned earlier are very valuable, but supporting multiple paradigms also introduces more complexity and more possibilites for develpers to produce un-maintainable code. There are many examples where using Scala or F# in a non-idiomatic way doesn’t bring much to the table.
I’ve seen Scala used as Java without semicolons. That surely doesn’t justify the complexity and the productivity hit deriving from using a slower compiler and from losing most of the support that an IDE would normally give. I’d be happy to pay these penalties to write idiomatic code but surely not to avoid a few keystrokes.
Usually multi-paradigm languages are fine when programmers are disciplined enough to choose one of the paradigms (hopefully the most idiomatic one) and stick with it. I wouldn’t go as far as claiming that an entire application should be written in a single paradigm, but at least avoiding mixing them inside a class or a module seems sensible to me.
As a counter-example, take an F# type. Make it extend a C# abstract class, sprinkle some mutable state and since you’re there add some members that take as parameters tuples, discriminated unions and curried functions. What you’ll obtain is a monster that’s I would try to avoid working with. Using it from C# is going to be clunky because of tuples and curried function. Albeit it’s technically F# code I wouldn’t want to use it from idiomatic F# code: mutable state and type hierarchy don’t play that nice with the rest of the language.
In conclusion, multi-paradigm programming language support different paradigms for a good reason. You should make sure to use this feature for that reason, steering as clear as possible from the hackery you can do misusing them. The recommendation is, as always, to write the most idiomatic code possible. The less idiomatic paradigm only should be used only in the very limited piece of your codebase where it makes sense and where it actually provides a benefit.