For example, what happens if a coder tries to code in purely functional-style paradigm in OO-paradigm language(Java)? Will it work? Or the OO nature of Java will not let it happen?
Also, is applying wrong paradigm to language unfitting to it a bad practice or not?
Is it like trying to drive a jet on road instead of flying it?
1
For example, what happens if a coder tries to code in purely functional-style paradigm in OO-paradigm language(Java)? Will it work?
Not well.
The parts of a language are oftentimes tailored to make common behaviors easy. Once you change what the common behaviors are, that design (usually) does not translate to the new requirements.
Also, is applying wrong paradigm to language unfitting to it a bad practice or not?
It is generally a bad practice. Programming languages serve two primary purposes:
- Telling the computer what to do.
- Telling other programmers what the computer is doing.
When you start deviating from the normal idioms of a programming environment, you start deviating from what other programmers know/expect/understand. Since nearly all programming projects these days involve teams, it’s considered a bad practice to make code that is hard to read, extend and maintain.
1
You can almost always shoehorn a paradigm in a language that doesn’t support that paradigm, but you’ll need lots of hacks and the resulting code will be some combination of ugly, complicated, inefficient, not idiomatic, etc.
That brings me to the second part of the question: Is it a good idea? Generally not, as it causes a great many downsides which are not worth any advantage the paradigm may have for the given problem (see above). However, I make an exception if a paradigm provides great benefits for the task and can be followed with reasonable ease, i.e., the aforementioned downsides are acceptable.
It really depends on which language and which paradigm, principle or pattern you’re trying to emulate.
I’d say the best practice is to use the language that is most suitable for your requirements, and study other languages to identify ways that you can improve the coding style in the language of your choice. But always approach a language on its own merits; utilize the unique strengths and character of the language you chose, rather than trying to shoehorn a paradigm that isn’t really a good fit.
OO and purely functional don’t form a dichotomy. “purely-functional” usually just means avoiding mutation, OO is a woolly term that IMO only acquires some concreteness when referring to the type system.
Somewhat oversimplifying, the general consensus is with larger, more complex, and more concurrent systems systems, mutation is increasingly an unwieldy tool.
If you try to avoid using mutation, your apt to discover however the verbosity of java et al becomes much worse. A lot of people blame OO, the real problem i think lies more with the influence of C and C syntax. Java gives you full-blown closures in fact, with anonymous classes, it’s just the syntax is ridiculously compare to languages that more ostensibly support them.
Again, the point here is not that OO and sparingly using mutation don’t mix, its that java is verbose. Scala I think is the foremost example where you have have tons of expressiveness, and an OO which frankly is purer OO than java.
http://www.drdobbs.com/architecture-and-design/interview-with-scalas-martin-odersky/231001802 An interesting interview with Martin Odersky, creater of Scala (and Java’s generics).
Coming from the opposite perspective, Haskell’s type system really lets you do a lot of what OO accomplishes, especially with extensions. Even if the underlying type theory is slightly different, the usage from a software engineering standpoint is quite similar.
Consider in Java, a common idiom is to write an abstract data type via an interface, and then call some methods in it on a heterogeneous collection, but one where all elements implement that interface. Well first of all, you can write a type class which does exactly what that interface does. Second of all, using existential types (an extension), you can build heterogeneous data structures and so on just like with Java. Just using a type class gives you polymorphism, but only static dispatch. Existential types give you dynamic dispatch.
http://www.haskell.org/haskellwiki/Existential_type <- more information on existential types.
so tl;dr if you pick a language with a strong enough type system and expressive enough syntax, you can stop worrying about paradigms and just do what fits your goal best.
1
It won’t work because there are things you just can’t do without draconian measures like writing a code generator (which is effectively making your own, new language). Of course, if both languages are Turing complete, you can get the same behavior – but the code is so different it isn’t reasonable to say you are really doing functional programming.
Let’s take a simple example – higher order functions.
Higher order functions are basic, bread and butter parts of functional languages. To use them, you need to be able to pass a function as a parameter. Java won’t let you do that. You have use the command pattern. This means you have to go create another class to hold the code for your command, instead of defining it in-line.
Worse yet, when your command gets evaluated, it is running in a different context than where it was defined. Variables that were in scope at that time may be gone. So, any variables that you need have to get stuffed into your command object so that they can get carried into the new scope. You have to do that manually, each time. If the language had lexical closures, the computer would figure this out for you.
By now, what would be, say, a simple call to map with a lambda function has turned into a small project, and the code looks completely different.
It just gets worse, too. Things like an algebraic type system checked at compile time just aren’t going to happen for you, ever.
You need to decide if a programming pattern makes sense in the language you are using, the fact that there is an elegant solution in a totally different language might help for inspiration but it can’t determine how you structure your code.
Most often it is not a great idea to try to directly write functional code, especially pure functional code, in OO languages. This seems to be the consensus around here.
A possible alternative is to do that “indirectly”, so to speak, by using a language that is binary compatible with your OO language.
For example, on the JVM you have Scala, or, if you want it more Haskell-like, you have Frege. Both languages can interface with Java. In fact, the Frege compiler creates Java source code and uses the ordinary Java compiler to compile it to bytecode, hence, writing Frege code could be seen as the most efficient way to write pure functional, non-strict Java code.
While Scala compiles directly to bytecode, as far as I know. But this does not hinder interoperability.
Likewise, instead of writing functional C#, you could try F#, which is essentially a ML dialect with support for .NET and C# interoperability.