Skip to content
GitHub Copilot is now available for free. Learn more

Artwork: Susan Haejin Lee

Functional programming is finally going mainstream

Object-oriented and imperative programming aren’t going away, but functional programming is finding its way into more codebases.

Klint Finley // July 12, 2022

The ReadME Project amplifies the voices of the open source community: the maintainers, developers, and teams whose contributions move the world forward every day.

Paul Louth had a great development team at Meddbase, the healthcare software company he founded in 2005. But as the company grew, so did their bug count. That’s expected, up to a point. More code and more features mean more defects. But the defect rate was growing faster than Louth expected.

“We were seeing more and more of the same types of bugs,” Louth says. “It was clear that there was an issue, but it wasn’t clear what it was. My instinct told me the problem was complexity.”

Louth and company used C#, which had just happened to add support for Language Integrated Query (LINQ), an alternate language for querying data sources ranging from databases to objects within codebases. LINQ introduced ways to apply the programming paradigm known as “functional programming” to C# code, and learning about how LINQ worked led him to learn more about functional programming in general.

Functions—chunks of code that can complete a given task again and again within a program, without the need to re-write the code over and over—are a standard part of programming. For example, you could write a function that returns the circumference of a circle when given its diameter, or a function that returns an astrological sign based on someone’s date of birth. But as Cassidy Williams writes in her guide to functional programming for The ReadME Project, functional programming is about more than just writing functions. It’s a paradigm that emphasizes writing programs using “pure functions”: stateless functions that always return the same value when given the same input and produce no “side effects” when returning their output. In other words, pure functions don’t change any existing data or modify other parts of an application’s logic. If our circumference function changed a global variable, for example, it wouldn’t be pure.

Graphic with two speech bubbles: one with a message window, and one with the Lambda symbol, the first concept introduced in Java

In functional programming, data is generally treated as immutable. For example, instead of modifying the contents of an array, a program written in a functional style will produce a copy of the array with the new changes made. Unlike object-oriented programming, where data structures and logic are entwined, functional programming emphasizes a separation of data and logic.

“When you think about well-structured software, you might think about software that’s easy to write, easy to debug, and where a lot of it is reusable,” writes Williams, head of developer experience at Remote, a company that uses the functional programming language Elixir for their back-end software. “That’s functional programming in a nutshell!”

Functional programming can be a boon for growing teams working with large codebases. By writing code with few side effects and immutable data structures, it’s less likely that a programmer working on one part of a codebase will break a feature another programmer is working on. And it can be easier to track down bugs since, as Williams writes, there are fewer places in the code where changes can take place.

As Louth delved deeper into the world of functional programming, he realized the approach could help solve some of the problems that large-scale, object-oriented codebases presented, such as those his team was starting to run into at Meddbase. He wasn’t alone. Interest in functional programming has exploded over the past decade as more and more developers and organizations look for ways to tame complexity and build more secure, robust software. 

“Once functional programming really clicked in my brain, I was like ‘why do it any other way?’” says Williams, who fell in love with functional programming during a college class that used the LISP programming language dialects Scheme and Racket. “Object-oriented programming isn’t bad, it still runs a lot of the world. But a lot of developers become evangelical about functional programming once they start working with it.”

Sure, object-oriented and imperative programming remain the dominant paradigms for modern software development, and “pure” functional programming languages like Haskell and Elm are relatively rare in production codebases. But as programming languages expand support for functional programming methods and new frameworks embrace alternative approaches to software development, functional programming is quickly finding its way into a growing number of codebases through a variety of different avenues.

Rise of functional programming in mainstream languages

Functional programming’s origins stretch back to the early days of programming languages with the creation of LISP in the late 1950s. But while LISP and its dialects like Common LISP and Scheme retained a devoted following for decades, object-oriented programming eclipsed functional programming in the 1970s and 1980s.

By 2010, interest in functional programming came roaring back as developers found themselves working with ever-larger codebases, and teams faced the same problems as Louth and his development team. Scala and Clojure brought functional programming to the Java Virtual Machine, while F# brought the paradigm to .NET. Twitter migrated much of their code to Scala, and Facebook deployed venerable functional languages like Haskell and Erlang to solve specific problems. 

Meanwhile, interest grew in applying functional programming techniques in object-oriented languages like JavaScript, Ruby, and Python. “All those languages increasingly support features that make it easier to do a functional style,” says Elm in Action author Richard Feldman. “Nearly every language is increasingly multi-paradigm.”

In 2014, Apple introduced Swift, a new, multi-paradigm language that includes robust support for functional programming. The launch proved that functional programming support had become a must-have feature of new programming languages, just as support for object-oriented programming already was. In a 2019 talk titled “Why Isn’t Functional Programming the Norm?” Feldman concluded that the functional style of programming is indeed becoming the norm. Or at least part of the norm. “Something has changed,” he said. “This style is not something people were considering a positive thing in the 90s, and the idea that it is a positive has become sort of mainstream now.”

The level and nature of support for functional programming vary by language, but one particular feature has become standard. “The thing that has seemingly ‘won,’ so to speak, is higher-order functions—functions that accept or return another function,” says Tobias Pfeiffer, a back-end engineer at Remote. “This lets you create blocks of functions to elegantly solve problems.” 

Support for higher-order functions has made it possible for developers to bring functional programming into their codebases without re-architecting existing applications. When Louth and his team decided to shift to a functional programming model, they settled on using F# for new code in existing applications, since it provides robust functional support while maintaining compatibility with the .NET platform. For existing C# code, they employed the language’s own support for functional programming, along with language-ext, Louth’s own open source framework for functional C#.

“A full rewrite wasn’t an option,” Louth says. “So when we add new features to existing code, we write it following a functional programming paradigm.”

For some, using an object-oriented language like Java, JavaScript, or C# for functional programming can feel like swimming upstream. “A language can steer you towards certain solutions or styles of solutions,” says Gabriella Gonzalez, an engineering manager at Arista Networks. “In Haskell, the path of least resistance is functional programming. You can do functional programming in Java, but it’s not the path of least resistance.”

A bigger issue for those mixing paradigms is that you can’t expect the same guarantees you might receive from pure functions if your code includes other programming styles. “If you’re writing code that can have side effects, it’s not functional anymore,” Williams says. “You might be able to rely on parts of that code base. I’ve made various functions that are very modular, so that nothing touches them.”

Working with strictly functional programming languages makes it harder to accidentally introduce side effects into your code. “The key thing about writing functional programming in something like C# is that you have to be careful because you can take shortcuts and then you’ve got the exact sort of mess you would have if you weren’t using functional programming at all,” Louth says. “Haskell enforces the functional style, it encourages you to get it right the first time.” That’s why Louth and his team are using Haskell for some of their entirely new projects.

But purity is often in the eye of the beholder. “LISP is the original functional programming language and it has mutable data structures,” says Pfeiffer. Even if your language is purely functional and uses immutable data structures, impurity is introduced the moment you include user input. While user input is considered an “impure” element, most programs wouldn’t be very useful without it, so purity only goes so far. Haskell manages user input and other unavoidable “impurities” by keeping them clearly labeled and discrete, but different languages have different boundaries.

Expanding the functional mindset

Even though functional programming is now available in most major programming languages, developers aren’t necessarily taking advantage of those features. The functional programming approach requires a substantially different way of thinking about programming than imperative or object-oriented programming. “What blew my mind was that you couldn’t do traditional data structures in functional programming,” Williams says. “I didn’t have to make an object for a tree, I could just do it. It feels like it shouldn’t work, but it does.”

Graphic with treasure chest, and inside is a Lambda symbol, the first concept introduced in Java

The JavaScript library React is one of the biggest ways that developers are exposed to this new way of thinking today. Because React allows for so much mutability, it’s probably best to think of it as “functional adjacent,” but the ecosystem does enable and promote functional solutions to common programming problems that would traditionally be solved with other methods.

“Even though it looked object-oriented, React provided the first functional-friendly approach to UI programming,” wrote David Nolen, maintainer for ClojureScript, a LISP dialect that compiles to JavaScript, in his story for The ReadME Project.

For example, the recently-introduced React Hooks are a set of functions that help developers manage state and side effects, while Redux—a popular library for managing state often used with React and other front-end libraries—takes a largely functional approach.

“React encourages people to think in a more functional way, even if it isn’t purely functional,” Williams says. “For example, it introduces front-end developers to the idea of using map and reduce functions instead of ‘for’ loops. You can now be a full-time front-end developer and never write a single for loop.” Check out Williams’ guide for an example of how this might work in JavaScript.

Meanwhile, Gonzalez sees functional programming becoming more mainstream through still another avenue: domain-specific languages. Being really good at one thing is often an easier route to adoption. For example, the Nix package management system’s expression language. “It’s even more purely functional than Haskell is, in the sense that it is even harder to write with side effects or mutability,” she says. Nix won’t be useful for, say, building a web server. It’s intended for only one purpose: building packages. But because it’s built for that specific task, developers who need a build tool might use it even if they wouldn’t otherwise try a functional programming language. “I think as time goes on you’ll see fewer general-purpose languages and more specialized languages,” she says. “Many of those will be functional.”

Building the future of functional programming

Like so much else in software development, functional programming’s future largely depends on the open source communities built around functional languages and concepts. For example, one barrier to pure functional programming adoption is simply that there are far more libraries written for object-oriented or imperative programming. From mathematics and scientific computing packages for Python to web frameworks for Node.js, it makes little sense for individuals to ignore all of this existing code that solves common problems just because it’s not written in a functional style. This is something Louth sometimes experiences with Haskell. “It has a fairly mature ecosystem, but it’s pockmarked by abandoned or unprofessional libraries,” he says.

To overcome that obstacle, the functional programming community will have to come together to create new libraries that make it easier for developers to choose functional programming over more side effect–prone approaches.

From the language-ext library to Redux to Nix, that work is already in progress.

About The
ReadME Project

Coding is usually seen as a solitary activity, but it’s actually the world’s largest community effort led by open source maintainers, contributors, and teams. These unsung heroes put in long hours to build software, fix issues, field questions, and manage communities.

The ReadME Project is part of GitHub’s ongoing effort to amplify the voices of the developer community. It’s an evolving space to engage with the community and explore the stories, challenges, technology, and culture that surround the world of open source.

Follow us:

Nominate a developer

Nominate inspiring developers and projects you think we should feature in The ReadME Project.

Support the community

Recognize developers working behind the scenes and help open source projects get the resources they need.

Thank you! for subscribing