Functional programming

Advent of Functional PHP: Day 2

Submitted by Larry on 2 December 2021 - 11:46am

In today's challenge, we're asked to interpret a series of basic command lines from a file and update the position of our submarine accordingly. It's basically a graph walk of sorts, with instructions of up, down, and forward. (Apparently you cannot go backward, as in life.)

As with yesterday's challenge, we could do it imperatively with a foreach() loop and a couple of state variables floating around, but that conflates a whole bunch of different behaviors into one blob of code. We don't want to do that, so let's step back and consider the problem more clearly.

Advent of Functional PHP: Day 1

Submitted by Larry on 1 December 2021 - 11:24am

Today's challenge asks us to interpret a list of numbers. In the first part, our goal is to determine how many elements in the list are larger than their immediate predecessor.

The imperative way would be to toss it in a foreach() loop and track some state along the way. But we want to be functional and avoid "track some state," because the whole point of functional programming is to avoid tracking state, as tracking state is error prone.

When looking at a foreach-style operation that has some state, my first inclination is to look at a reduce operation. A reduce operation walks over a list and performs the same operation (function) on each item, using the output of the previous iteration as an input. That is, each step takes the output of the previous operation and the next element, and produces an output. It's quite elegant.

Advent of Code 2021: Functional PHP

Submitted by Larry on 29 November 2021 - 6:45pm

I am planning to participate in Advent of Code this year. For those not familiar with it, it's a daily coding challenge that runs through December, until Christmas. Mostly it's just for fun, but some people take it as an opportunity to either push themselves (by solving the puzzles in a language they're unfamiliar with) or to show off some feature of a language they like, which they then blog about.

In my case, I'll be solving puzzles in PHP, of course, but specifically using functional techniques. My goal is to demonstrate how functional programming in PHP is not just viable but creates really nice solutions. At least, I hope it works out that way; I haven't seen any of the challenges yet. :-)

The case for partials and pipes in PHP

Submitted by Larry on 23 June 2021 - 3:07pm

The Partial Function Application RFC is currently in voting, and right now it's a close vote to the negative. I wanted to take this opportunity to try and make the broader case for partial application and for its related RFC, the pipe operator, in a way that is more appropriate for a blog post than the RFC body (which is, by design, more concerned with the finer details of "what").

The main pushback on the RFC so far is that the benefits don't outweigh the cost of yet-more-syntax in the language. Which is a fair position to hold, albeit one I hope to convince you is incorrect. That is, I believe the benefits vastly outweigh the syntax and implementation cost.

One year of functional PHP; now in Russian!

Submitted by Larry on 11 May 2021 - 8:14pm

A year ago, I published my first solo book, Thinking Functionally in PHP. The reception has been extremely positive; almost everyone that's read it (that has bothered to talk to me about it) has found it clear, helpful, and enlightening. Mission accomplished!

To celebrate the one year anniversary of the book's publication, I am happy to make two announcements.

Byte-sized functional programming: Composition over inheritance for functions, too

A popular refrain in object-oriented code is to favor object composition over inheritance. It offers more flexibility, less overhead, and ends up being easier to reason about. The same concept applies to functions, too!

A common pattern is to have a function that does some work and then calls another function, which does some work and calls another function, and so on. The problem is that the first function then cannot be used or tested without the entire chain of other functions it calls. This is the function equivalent of "inheritance."

Instead, we can compose functions, that is, pipe them together. Instead, take the output of the first function and pass it to the second, then take the second's output and pass it to the third, etc. That way, each of the functions can be reused, tested, and understood in isolation, then we can stick them together like LEGO blocks to build whatever series of steps we want.

That is, instead of this:

Larry 15 August 2020 - 10:07am
Byte-sized functional programming: Filter first

Often when working with a list, we only want to work with a subset of a list that meets some criteria. All non-zero values, for example, or all users that have a given role. The procedural way to do that is to stick an if statement inside a foreach loop:

foreach ($list as $value) {
    If (!meets_criteria($value)) {
        continue;
    }
    // ...
}

That mixes up the filtering with the iteration, though. It also doesn't work if we're using array_map().

Instead, we can make stripping down the list a separate operation called "filter." PHP offers the array_filter() function for that purpose.

Larry 3 August 2020 - 1:47pm
Byte-sized functional programming: Mapping out your data

Procedural code tends to think in terms of writing out steps, and so the usual way to work with a list is to iterate it using a `for` or `foreach` loop.

Functional code tends to think in terms of the relationships and transformations between data, where those relationships and transformations are defined as functions. That means the natural way to work with a list is to define a function that is the relationship between one list and another. The most common way of doing that is with a "map," which in PHP usually means the `array_map()` function.

Larry 27 July 2020 - 3:42pm
Byte-sized functional programming: Immutable variables are easier to understand

An immutable variable is one whose value doesn't change after it has been first set. PHP doesn't natively support that, but we can write our classes in such a way to simulate it. For example, rather than this:

class Point
{
   private int $x;
   private int $y;
  
   public function __construct(int $x, int $y)
   {
       $this->x = $x;
       $this->y = $y;
   }
  
   public function moveUp(int $by): void
   {
       $this->y += $by;
   }
}

We can write this:

Larry 21 July 2020 - 7:30am
Byte-sized functional programming: Pure functions make testing easy

When testing stateful code, you have to first set up all of the explicit and implicit state that a given piece of code depends on. If the object you're testing has many dependencies that could be complex, or references global variables, or calls many other routines with their own dependencies, you may be looking at a lot of complex setup that makes testing hard to do effectively.

Pure functions greatly reduce that problem.

A pure function is a function that:

  • has no inputs other than those explicitly specified;
  • has no effect on any value other than the value it returns.

That means there is, by definition, only one place to inject dependencies: the call itself. And there's only one effect to validate: the return value of the function. No need to call a function and check what the effect was on some other value or piece of code: by definition, the only effect is the return value.

Larry 14 July 2020 - 9:28am