Garfieldtech

Technical thoughts, tutorials, and musings

Blog

Advent of Functional PHP: Day 2

Posted:

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.

The first thing to realize is that we're tracking some value over time, our position, which is getting modified by each instruction line in the file. Said the other way around, we're iterating over a list of commands and each one is updating the position, using the result of the previous instruction as a starting point. "Walking a list and updating a value each time" should trigger our functional brains to say "ah ha, a reduce operation!"

As noted yesterday (I didn't know what today's challenge would be, I swear), 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. It also goes by the name "fold" or "foldl" (fold left) in a lot of more academic posts; same thing. But it fits our use case exactly: Given a start position and a list of "change position" commands, apply each command to the position in turn, returning a new position each time.

Advent of Functional PHP: Day 1

Posted:

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.

However, reduction operations only allow you to pass forward one intermediary result. In our case, the input to a given operation is the current element and its predecessor. That can be squeezed into a reduction operation if we try, but it feels awkward to me, so I'm going to allow some for-style loops. As long as they're controlled, that's OK.

Let's think about the steps involved in our problem:

  1. Read the input file in from disk.
  2. Break it up into a series of integers (or numeric strings, which for PHP is close enough).
  3. Determine which of those elements is larger than its predecessor.
  4. Count the number of elements that pass the test in step 3.
  5. Profit!

Advent of Code 2021: Functional PHP

Posted:

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. :-)

I will be using the just-released PHP 8.1, because it's a really nice release that I am already in love with. I will also be either using or extending a small functional library I've built recently to support my own projects, Crell/fp. Mostly it's built to support pipe operations, by providing a user-space pipe() function (since a syntactic one sadly didn't get accepted to PHP itself) and a series of functions that return closures in order to play nicely with it.

A secondary goal of this endeavor is to help flesh out that utility library more. :-) (It doesn't even have any common monads yet, like Either, which I expect I'll end up making along the way somehow.)

Each day, I will blog my PHP solution to the problem to share with the rest of the community in the hopes that it will be educational. At least, each day until I decide I can't keep up with it. We'll see how long I last...

Let the coding commence!

The case for partials and pipes in PHP

Posted:

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!

Posted:

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.

First, Thinking Functionally in PHP is now available in Russian! The translation is by Alexey Pyltsyn, who is responsible for the Russian translation of the PHP documentation as well as numerous other tech book translations.

Second, to celebrate the anniversary both the English and Russian editions are now on sale! For today and tomorrow, the minimum price for the English version has been reduced to just $20 USD. The Russian edition's introductory price for the next week is only $10 USD. (Both prices are only through those coupon links.)

If you haven't picked up a copy yet, now is the time. If you have, it's a great time to gift a copy to a friend or colleague. :-)

Byte-sized functional programming: Mapping out your data

Posted:

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.

Byte-sized functional programming: Pure functions make testing easy

Posted:

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.