Apps

When to use functional programming languages and techniques

If a project requires lots of concurrency/parallelism, its own language, or lots of math, you should think functional programming.

As IT professionals, we have to balance proficiently executing on current projects with proven technologies and learning to implement new ways of doing things. Software development arguably changes more rapidly than any other aspect of IT, making it an even tougher challenge.

Given the limited amount of time, it’s often difficult to decide what new techniques to learn. The questions of if and where to use functional programming languages/techniques strikes me as one of the tougher calls to make these days.

If and where to use functional programming

First, let’s define our terms. A functional language or technique is one in which the sole or dominant form of expressing algorithms is the evaluation of mathematical functions, avoiding state changes and mutable data. This is as against declarative, imperative, and procedural languages/techniques, which emphasize changes in state.

There is a strong case to be made that either functional languages or the other kinds can be object-oriented. LISP, considered by many an archetypal functional language, is a prime example. In other words, you can use either kind of language to implement object-oriented principals (and some would argue, more “purely” in functional languages). Similarly, you can write bad code in any language.

So, what kinds of problems are functional languages (if used well) superior at solving? Surveying the literature, problems that require lots of concurrency and parallelism jump out as obvious candidates. Erlang, for instance, was used prominently at Ericcson in the telecommunications equipment field, and more recently to power messaging startup WhatsApp. Interestingly, the famous Lucent (via Western Electric, not Bell Labs) 5ESS telephone switch is another example of a prominent functional programming success story. If you’ve placed a phone call to or in the United States in the last 30 years, chances are you used one of these devices, and the code that keeps its database (with more than 1,000 relations) consistent, was written in a custom language called Pdiff, which in turn was written in Standard ML.

That brings us to another area where functional languages seem to shine: domain specific languages (DSLs). If your problem domain is so hairy that the usual design patterns we're used to in typical enterprise languages like Java and C/++ fail to efficiently solve them, a DSL might be just the trick. You wouldn't build your whole system with a DSL, but, like the 5ESS switch, you could use it to code a critical function in a way that is easier to understand and maintain and, therefore, ensure its quality. Functional languages are killer at creating DSLs.

One interesting example I found is a DSL to process exotic financial derivatives. This illuminates another area where functional languages/approaches shine: math-heavy algorithms. If you need to solve a problem that can decompose into a series of mathematical operations, the kind of thing you’d tackle with a DSP chip or GPU, then a functional language is likely a good choice for expressing the solution.

Another way to think about this kind of problem is: Could you solve it, at a small-scale, with a spreadsheet? If the answer is yes, then you’ve got two choices: get a product that can compile spreadsheets into your platform of choice (many exist), or express it in a functional language. This is a useful analogy, because it highlights how functional languages (which seem so math-centric) can handle operations we’re used to in other languages, like conditional statements. If you’ve ever used the IF function in a spreadsheet, then you have your answer. Functional languages, like the other kinds, are Turing Complete, and can be used to code any problem. The trick, it seems, is to code different parts of your system in languages that are most effective at expressing that part of the problem domain.

Great, so, I’ve got you interested in functional programming, now what the heck do you? When trying to build a new capability within my team, my preferred approach is to identify a potential pioneer. Someone who can grok the new ideas, drink the proverbial punch, and then bring that knowledge back to the team and evangelize. Send that person out for training, and then (as I think you should do with any training course) have them share what they learned with the team (buy them all a meal at the same time too, it helps). But only do so when you’ve identified a project or task where a functional approach makes sense. If folks don’t start to use what they’ve learned within 30 days, it’s likely gone.

If you want to incorporate functional code into your larger system, one approach is to have the language compile into the same bytecode as your main system; Scala runs on JVMs, and there is F# for the .NET CLR (and other platforms). You can always just run your code in one of the other functional language environments (such as Haskell, Clojure, OCaml, etc.) and expose it with a REST API as well.

The bottom line

If a project requires lots of concurrency/parallelism, its own language, or lots of math, think functional programming.

Article discussion

I’m coming at this issue from the perspective of someone who has been managing software development for over 20 years. I’m focusing on the questions: “Does this tool belong in my toolbox?" and “What kind of problems can I fix with it?” I hope the related discussion doesn't devolve into the near religious fervor that often accompanies discussions about which programming language is better for what application.

Also read on TechRepublic

Keep your engineering skills up to date by signing up for TechRepublic's free Software Engineer newsletter, delivered each Tuesday.

About

Claudio Caballero is COO of Palomar Systems, a software development and systems integration firm in Bangkok, Thailand. Prior to returning to Asia from his native New York City, he was an IT consultant for 12 years, beginning as an Engagement Manager ...

9 comments
info.shanayamail
info.shanayamail

Problem with Functional Programming

There are basically four problems with the functional programming listed below:- Reusability, Extensibility, Simplicity, Maintainability


read more in brief

just.a.guy
just.a.guy

SQL, to me, seems to be designed for parallel processing. It is not great for mathematically intense computation. If you have a "towers of hanoi" type problem, recursion is your best approach. But a spreadsheet is nothing but a type of table. That data structure is made for SQL. The problem in the current IT environment is that programmers only know how to write simple insert, update, delete, and select statements. With those simple statements, they fall back on the procedural language. Much of the data manipulation, filtering, and decision structures can be accomplished within SQL statements, without have to bring the data across the database connection. With partitioning of tables, and advanced indexes the actual work in accessing and maintaining large database using parallel processing is much easier than it was 20 years ago. And if you run out of steam, buy more hardware or balance the load or increase the degree of parallelism. The application code (the SQL statements) does not change. The problem with using SQL is you have to change your mindset. In procedural code you handle one record at a time and then repeat the process (in a loop) across the entire dataset. To write an application in SQL, I have found it easier to think in terms of data flows, and producing a pipe network to accomplish the final goal. I try to let the SQL engine optimize the flow. What do you know, it produces byte-code. It did this before Java type languages existed. If you look around, there might be a functional language right under your noses.

bcasner
bcasner

This sure sounds a lot like Forth, written way back when. Everything is a function, and defining a new language is considered essential to writing any program.

Claudio Caballero
Claudio Caballero

Great points all, Mark. Thanks for drilling down into details I can't cover within my word limit.

Mark Miller
Mark Miller

[i]A functional language or technique is one in which the sole or dominant form of expressing algorithms is the evaluation of mathematical functions, avoiding state changes and mutable data. This is as against declarative, imperative, and procedural languages/techniques, which emphasize changes in state.[/i] I found a couple problems with this statement, but I think it's a matter of definition. I think what you mean by "change state" is being able to say: [pre] // print range for(int a = 1; i < 10; i++) {printf("%d ", a);} [/pre] and iterate from 1..10 by changing the value of 'a'. This state change takes place inside the same memory context. In pure functional programming, it's true you aren't supposed to do this (and some FP implementations probably won't allow it), but in FP you change state via. function call. So in pure FP it's legal to do this (coding in Lisp): [pre] (defun range (a limit) (cond ((= a limit) nil) (t (cons a (range (+1 a) limit))))) (print (range 0 10)) [/pre] When range is first called, the state of 'a' is 0. When it's next called, from inside the function body, 'a' is 1, and so forth. 'a' can be said to have changed state, but via. a function call. The value of the variable has changed, executing over the same code. This still maintains immutability, because each function call contains its own memory context, which disappears once the function call returns, and an older state is restored in the current scope. 'a' can be said to iterate over the same range as the above C++ example, but it does it by a different mechanism. In this case, it's commonly recognized as "recursion." Functional code can also be declarative in the sense of constructing relationships between data. I came up with this example a while back. Say you're constructing a data structure showing the relationships between assemblies and sub-assemblies that make up a motor. It can be done like this (again, in Lisp): [pre] (setf *motor* '(:assembly A ((:part "partNumber1") (:part "partNumber2") (:assembly B ((:assembly C ((:part "partNumber3") (:part "partNumber4") (:part "partNumber5"))) (:part "partNumber6")))))) [/pre] This is probably not considered pure FP code. To do that, you'd use a [pre](let ...)[/pre] expression, which would bind the list to a temporary symbol, and execute code on that binding. To be clear, this list is not evaluated. It's a series of symbols, strings, and lists related to each other. This is equivalent in an imperative-style OO language to embedding a series of containers inside each other. With some modification, this could be set up using dictionary/hash containers in one of those languages. In any case, I think it would be a lot more work to construct. One can see obvious parallels to how data is laid out in XML. Think of it as XML with "begin" tags, but the "end" tag is just the right-parentheses that marks the end of a list. Once this list is constructed, it can be traversed/searched using recursive descent.

Mark Miller
Mark Miller

I realized a year or two ago that typing out a command line in a Unix shell with pipes is also functional programming, though using a scheme more akin to postfix, rather than prefix notation. If you imagine a set of nested function calls, each one inside the parameter list of the previous one, in a prefix "mode" functional language, the rightmost (and innermost) function gets evaluated first, whose result is returned to the outer function call, which is then evaluated, etc., going from right to left. In shell programming the "innermost function" is on the left, and results propagate to functions towards the right. The difference is the implementation allows processing of partial results through the pipeline. Re. SQL To me, SQL has involved applying filters to functions, with the exception of commands like "CREATE TABLE". In functional languages I've used you can create your own functions. I don't see where you do that in SQL, unless you're talking about a particular language for creating stored procedures, which in every case I've seen is a proprietary extension of the language. I can see where T-SQL (Microsoft) would give you the feel of FP, but PL/SQL (Oracle) (or has that been deprecated to Java?) looks a lot like Visual Basic code.

just.a.guy
just.a.guy

I see functional programming different from procedural programming. The major difference is in the concept of flow and the degree of parallel processing. Functions are a major component of functional processing. As SQL has developed each vendor has seen the need for user written functions. Each has implemented their unique brand of this capability. This arose out of a time, when large IT vendors saw competitors in a zero sum game. They used differences in their software to lock their clients into their products. It is almost impossible to switch vendors when you have large amounts of software that has to be examined, modified or rewritten. There was big money at steak for the vendors. Only large corporations had the resources to buy, build, and use information technology. PCs did not enter the environment along until at least 20+ years after the first computer (large mainframe). Database systems were already on the scene. Unix was among the first to attempt to create a non-branded (open) environment, in a time when the branded giants ruled the world of IT. However, when it comes to functions, a capability is capability, vendor specific or not. Seeing SQL as filters applied to functions is one view point. I see it as functions applied within flows. It is sort of like saying the earth goes around the sun, or the sun goes around the earth. Both view points are valid. VIEWS and TRIGGERS, provide a capability similar to UNIX pipes. Both T-SQL and Oracle implement them. A major difference between UNIX scripts and SQL lies at the heart of the SQL engine. The SQL engine is the design for concurrent processing by multiple threads through the data. Locking can be at the table, block or row level. For UNIX scripts locking is at the OS file level. Because of this Unix scripting is at a disadvantage in terms of parallel processing. It has been awhile since I wrote UNIX scripts using pipes. For me they are always a single thread process (maybe I am ignorant of their full capability). If I wanted to create a second thread I would have to fork the process. This change was hard coded into the script. SQL has introduced control of parallelism outside of the SQL statement definition. A DBA can change the degree of threads through the data without having to ask the programmers to modify their code. The capability of controlling the degree of parallel processing out side of the code definition seems to be an essential requirement for a functional language.

Mark Miller
Mark Miller

I don't see how parallel processing is "at the heart" of functions. If you look at a lot of implementations of functional programming languages, parallel processing is not at the heart of them. They are designed for single-thread execution. Computer science theory says that pure FP enables one kind of easier implementation of parallel processing, because of the lack of side-effects. Lazy evaluation offers potential here. It's just a matter of having a runtime that enables parallel execution of functions, which is what you've discussed with RDBMS's. It's not an artifact of the SQL language, but rather how it's implemented. MySQL, for example, does not offer the same level of parallelism that PostgreSQL does, or SQL Server, or Oracle server. As for Unix, even though it offers file locking, it is possible to allow multiple processes to update the same file at the same time. This is not accomplished through a shell script, but rather through a language like C, which can call a system library function to allow this. I know, because I wrote a server process for Unix many years ago that did this. It's not hard to do, though once you enable file sharing, my understanding is the OS allows just about anything to happen. It only locks on the byte level. It's up to the processes that operate on the file to mind where they should and should not read/write. I'm pretty sure Oracle and other RDBMS's take advantage of this, because after all, even though they allow parallelism, if there are multiple requests on a single database, unless the database is distributed in a cluster, the parallelism in fact happens inside of a single process, probably with multiple threads, operating on a single file. There is a kind of parallelism that happens in Unix pipes. It offers a "flow of functions," like you were saying. Like I was saying earlier, unlike the typical FP implementation, Unix is typically implemented such that processes which are linked together by pipes can process partial results. If you have: [pre]ProcA | ProcB[/pre] ProcA can be outputting data one byte at a time, and ProcB can be consuming those bytes while ProcA is still in the process of doing whatever it does. However, ProcA is in the driver's seat. For example, it could output data one line at a time, instead of one byte, though as far as ProcB is concerned, it doesn't care, since to it, the input always looks like a stream of bytes. Other than named pipes, and file locking, this sort of on-the-spot piping is the only case I can think of where this parallelism is allowed. Each statement in a shell script is executed sequentially, unless it's explicitly forked, although I can imagine some enterprising programmer coming up with a scripting language for Unix that allows implicit parallel execution of statements. It's not out of the realm of possibility.