Your Privacy

This site uses cookies to enhance your browsing experience and deliver personalized content. By continuing to use this site, you consent to our use of cookies.
COOKIE POLICY

Skip to main content

Diving into Functional Programming

Diving into Functional Programming
Back to insights

Programmers have been writing code for decades now.  Billions of lines, gallons of coffee and countless hours in front of a keyboard.  Over time, patterns and styles have emerged to make the task of building and maintaining code much easier.  This is an ongoing process which has gone through many eras.  From machine code to procedural code to patterns that are widely used today like imperative and Object-Oriented Programming (OOP), programming languages try to follow one or more of these paradigms to help facilitate development.  Lately, one paradigm has been showing up in more and more languages due to many of its useful qualities.

Functional programming is a style of computing that treats a program like the computation of mathematical functions. Like a math equation, all function in this paradigm are deterministic.  This means for any given input, the output will always be the same no matter how many times it is called.  Since functions are such a critical part of functional programming, they are considered first-class functions.  What this means is a function is treated like any other entity in a program such as an object or a number.  They can be assigned to a variable and passed to another function.  That function is called a higher-order function which means it can take a function as an input and/or return a function as an output.  This behavior is used extensively.  In this paradigm functions are said to be pure, meaning there are no side effects from running the function.  What is a side effect?  Anything that changes the state of the application or mutates an object.  It doesn’t matter how you call or interact with the functions as long as the inputs do not change, the output does not change.

This behavior allows functions to be run in parallel since they are by definition, thread-safe.  They also allow environments to safely cache commonly run functions since the same inputs will always produce the same output.

This is great at a lower level, but what advantages are there for a developer to learn functional programming?  My motivation was to learn different ways to solve problems.  With many languages like Java and Python, there is a tendency to write programs in an imperative way using state and mutable data when often times it is unnecessary.  Manipulating a data structure instead of returning a new one has a tendency to cause bugs and hidden behavior.  Functional programming is a way to explicitly say what should happen in a program.  Another reason to learn this program is because many of your favorite languages have implemented aspects of it.  While these languages are not a pure functional language like Haskell, they aim to incorporate some of the great aspects of the paradigm.  Java 8 made a big leap into functional paradigms with first-class and lambda functions.  JavaScript, Groovy, Scala and more offer extensive ways to use and create functions.  It is a great idea to isolate some of these concepts from imperative or OOP ways to developing code to see how powerful they can be.

Some of you may be wondering how purely functional languages handle non-deterministic behavior.  After all, the world isn’t as simple and clean as a carefully constructed math problem.  How does a purely functional language deal with concepts like IO, Randomness and error handling?  All of these concepts produce side effects which break the paradigm and seemingly make pure functional programing impossible.  Like a shrewd lawyer, functional programming has an answer.  While a function cannot cause a side effect, it can create a value to describe a desired side effect that the caller applies. In pseudocode:

The state of the program is given to a function, and when it changes it returns a whole new state, it does not overwrite what currently exists.  A similar concept exists in the Javascript framework React where the previous state is not overwritten but replaced by a new updated state.  In Haskell, side effects are encapsulated in a concept called monads.  This may need to be made into another blog post, as the concept can be complex.  At a high level, monads determine how side effect causing behavior can be used in functions and what rules other functions need to follow using these types.  For example, there is a monad called “Maybe.”  Like Schrödinger’s cat, it is a type that may or may not contain a value. This value cannot be determined until the program is running, and as such any functions using a Maybe monad output, need to be prepared for both cases.

Functional programming aims to make development like evaluating mathematical functions.  This style avoids changing the state of a program and cause unintended consequences.  This is a style to avoid errors due to mutable data and simplifies testing.  It can handle side effects causing behaviors like interacting with memory or IO using functions that describe the side effect, so it can be dealt with transparently.  Functional programming elements are showing up in every major language and it is worth checking them out to augment your code.

Digging In

  • Software Engineering

    The Transaction Is Not the Finish Line

    What happens when you treat the post-transaction journey as the product? Picture this: you’ve just purchased a home. And then… nothing. Weeks go by. You’re not sure what stage things are in. You’re waiting on updates from different teams, across different systems, with no clear view of what’s happening or what happens next. If you’ve […]

  • Software Engineering

    When There’s Too Much to Fix: How Smart Prioritization Unlocks Revenue at Scale

    Every operations team has a backlog. The question isn’t whether you can clear it — it’s whether you’re clearing it in the right order. For most teams, the honest answer is no. And that gap between the order work gets done, and the order it should get done is quietly costing organizations millions. The Volume Problem High-volume exception processing shows up across […]

  • Software Engineering

    Creating Reusable Code Templates to Reduce Client Project Startup Time

    In consulting, one of the least visible but most expensive phases of a project is the beginning. Teams can spend days or weeks setting up repositories, agreeing on structure, wiring basic infrastructure, and solving problems that have already been solved many times before. Code templates are a practical way to reduce overhead while improving consistency. […]

  • Software Engineering

    Player Three Has Entered the Game: How AI Is Finally Bridging the Divide Between Design and Engineering

    As AI begins to become more prominent in our day-to-day lives, I find myself in a unique position. As a practicing software engineer and UI/UX designer, I am genuinely happy to see the introduction of AI tools begin to take shape in our industry. But more importantly, I am happy to start seeing the effects it is having on what has historically been a pretty challenging relationship: the […]

  • Software Engineering

    The Disappearing Middle of Software Work: Why the Bookends – Strategy & Impact – Matter Most Now

    Here’s a question nobody in enterprise software wants to sit with: what happens to the middle? Not the middle of the org chart. The middle of the work. The vast, expensive layer of effort that has defined enterprise software delivery for thirty years—translating what the business wants into working code. The requirements-to-implementation pipeline. The “build phase.” […]

  • Software Engineering

    Zero-Code Telemetry with OpenTelemetry’s OBI

    Full distributed tracing and exception capture for any application — without writing a single line of instrumentation code. View the source code on GitHub → The Premise Observability is essential for understanding what’s happening inside your services, but instrumenting an application by hand — adding trace spans, logging calls, and metric counters throughout your codebase […]