I know there are different ways to combine programming languages (Haskell’s FFI, Boost with C++ and Python, etc…). I have an odd interest in combining programming languages; however, I have only found it “necessary” once (I didn’t want to rewrite some older code). Also, I notice that this interest is shared (there are an abundance of questions about integrating languages on SO).
My question is, simply, are there any other benefits in combining programming languages? Is there value in mixing different programming paradigms (e.g. functional+OO, procedural+aspect-oriented)?
Any from-the-field examples would be much appreciated.
UPDATE
When I say “combine two languages” I am talking about using them in conjunction, in ways not necessarily originally intended. For example, suppose I use Boost to incorporate Python code in C++.
2
A typical example shows up in the Computer games, particularly AAA titles where a C++ backend is the norm. The interface section will often be designed in a scripting language such as Python or Lua. This allows for easy modification by both the developers so they can test out new interface designs without messing with the highly complex physics and graphics engines underneath and at the same time allows for easy modification by players who may not have the coding chops to handle a full game engine but can competently do a few interface tweaks.
Another widespread use case is the web itself. Javascript, CSS and HTML combine to form a front end with whatever you want as a backend on the server. Windows 8 apps use a similar approach with the declarative XAML defining interfaces and providing class outlines while C# fills in the details and runs the thing.
Thus, the typical divide will be a fast, statically typed language running a solidly tested codebase handling heavily numerical work with a scripting language running on top of it to provide easily changeable frontends handling visual and presentation functions as well as input.
Other use cases exist as well. Data processing languages like R can be bolted on to other codebases to provide analytic and presentation functions more easily than the native codebase might be able to. As far as combinations of paradigms, a combination of Prolog for database work and some other language to handle the standard program functions is a known case. Another case would be having Fortran or Assembly routines for fast numerical computation within some scripting language like Python. Which is exactly what Numpy and Scipy do.
Programming languages are fundamentally abstractions that assist in helping you tell a computer what to do. As they are abstractions, this means that they hide some of the details and so simplify the overall task, enabling you to comprehend how to do some particular piece of programming without having to understand the whole thing at once. But that hiding also means that they restrict what you can do: going outside the abstraction is hard, and so also is having to build a lot of new abstractions on top of the base level provided by the language.
The net effect of this is to mean that a particular programming language has a range of programming tasks that it is well suited to, but it is not going to be good for everything. A low-level programming language allows you to do low-level work, often that happens to be performance critical (such as numeric-heavy processing). That’s OK, but doing high-level work in the same language is nothing like as easy as using a language that specializes in higher-level abstractions. What’s more, there’s no perfect set of abstractions to choose: some problems are better described in one group (e.g., functional programming), and others require a different approach (e.g., logic programming).
The best way out of this situation where a programming language that can do one task isn’t good for others is to use multiple programming languages. Let each language focus on doing the tasks that it is good at, and then transfer control to code written in another language for other parts. It’s specialization (and also componentization) and it is a good thing indeed. Of course, there are languages that happen to work particularly well together since they have strongly compatible ABIs (e.g., Java and Scala, C# and VB, C++ and Lua) but they’re most certainly not the only levels that you can plug things together at. Indeed, when you’re accessing a web service you’re probably using the same ideas: the languages that clients are written in are probably not those that servers are written in because, even if there’s no theoretical reason for a language to be unable to do both sides, some languages have better abstractions for one side or the other.
Another example that was not mentioned is the use of a new programming paradigm with existing legacy code and / or libraries.
For example, Java has tons of existing libraries and frameworks that can be used directly by new languages like Scala and Clojure. In this way, one has the advantage of using a clean implementation of a different programming paradigm that is not supported by Java, while retaining backward compatibility with legacy code and existing libraries. (I chose Java, Scala and Clojure but there are probably other examples I do not know of).
There is no such thing as a “general purpose” programming language. Every language is strong in one area and useless in the others. Therefore, in a complex project which covers many different problem domains it is most efficient to use multiple languages. As far as I know, there are no benefits whatsoever in using a single language for a project where you can use multiple languages.
Of course, the most efficient language for any given problem domain is a language tailored specifically for this narrow domain. This approach is known as Language Oriented Programming, and such languages are called Domain Specific Languages. But even if you, for some weird reason, do not want to implement you own languages, there are multiple ready to use languages out there, and picking one most suitable for a task still will be much more efficient than using a language which does not fit well into the problem domain constraints.
One of the most efficient and convenient way of mixing different languages together is using embedded DSLs hosted inside a single meta-language. This way you won’t need any FFI, you can reuse features of your host language library from within your DSLs, you can reuse your host language optimising compiler.
Another common approach is to host different languages within a runtime of a single common VM, like Java+Clojure+Scala or C#+VB.NET+F#.
20
I would say the benefit is to get the most expressive and best performing solution to the problem at hand. Also, embedding one language in another often lets you move to a higher level of abstraction for parts of your work.
I am doing IOS development, so naturally I am writing in Objective-C++, which gives the awesome power and complexity of C++ and the run-time binding and introspection of Objective-C. I would think this is perhaps the most popular “hybrid” language/paradigm currently. Often I will write .mm (objective c++) files with mostly C++ and STL and just a little Objective-C. For example, last week I wrote a state machine in C++ that called back into an Objective-C object to perform its actions. Writing the machine in C++ was easier, more expressive, and reusable.
In this particular project, I also wrote a scheme interpreter which is embedded in the program and is used to control a communication channel by writing scheme at runtime based on environmental conditions. Scheme is a good choice for this because it is so small, simple and “code is data.” It also raises the level of abstraction, and a functional approach works well in this situation.
I don’t find embedding little languages to abstract complex problems unusual at all. Be it a set of tokens in a string that control an interpreter to drive some complex decision tree, or a full-blown specialty language of my own design or a unique problem, or a more off-the-shelf solution like LUA.
Tkinter is a graphical library for Python that is built upon Tcl/Tk. It’s actually an embedded Tcl interpreter that is called from python. Normally this goes mostly unnoticed, but it’s possible to put tcl code in a string and run it directly in the interpreter. This lets you do things that the native tcl/tk can do that Tkinter cannot because of an incomplete implementation.
Two examples:
- Wrote a system that imported CSV and XLS spreadsheets into a database using custom mapping documents. Wrote that system in Java and it worked fine. Then came the requirement to read those documents from an FTP server that would need to be polled at set intervals. Ruby’s perfect for that, could write that code far more efficiently in Ruby than Java. So wrote a Ruby script to poll and retrieve the documents, which fed them to the original Java application which still could be called standalone as well for additional inserts or testing
- Working on a system written in an old language that’s probably going the way of the dodo soon (losing support from toolvendors, training providers, etc.). Porting the entire system to a new environment in one go would be too risky for the business, take too long to please marketing, and deny customer new capabilities they’ve been asking for. So we create for several releases a hybrid system, with part created in that old technology and part in the new, gradually transiting from one to the other until in a year or two maybe the old will all have been retired.
- Every system using web services (or other EDI) to communicate is inherently hybrid at least in potentiality. It doesn’t matter for your client whether the web service provider is written in Java, C#, Cobol, or whatever as long as the documents exchanged are in a format that both sides understand. Makes for great flexibility in case you have several teams working side by side that have different skill sets. Each can employ what technology it knows best, the end result will be better as a result.
If there actually is a benefit in mixing two languages, soon enough either one language picks up elements or concepts of the second one, or a new language emerges “between” both languages (one could argue that this happened with Scala, which pretty much sits in the “middle” between Java and Haskell).
9