Page
1
Functional Programming in PHP A Primer for Composing Software in PHP — Michael Bruno Lochemem
Page
2
Functional Programming in PHP
Page
3
Michael Bruno Lochemem Functional Programming in PHP A Primer for Composing Software in PHP
Page
4
Michael Bruno Lochemem Nairobi, Kenya ISBN 979-8-8688-2467-8 ISBN 979-8-8688-2468-5 (eBook) https://doi.org/10.1007/979-8-8688-2468-5 © Michael Bruno Lochemem 2026 This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication does not imply, even in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore free for general use. The publisher, the authors and the editors are safe to assume that the advice and information in this book are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the editors give a warranty, expressed or implied, with respect to the material contained herein or for any errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional claims in published maps and institutional affiliations. This Apress imprint is published by the registered company APress Media, LLC, part of Springer Nature. The registered company address is: 1 New York Plaza, New York, NY 10004, U.S.A. If disposing of this product, please recycle the paper.
Page
5
Acknowledgements I would like to begin this list of acknowledgments by recog- nizing the efforts of the Apress team that facilitated the completion of this book. At the time of discovery by Divya Modi, the original work, which was published on Leanpub, though coherent, was in need of improvement. In providing an avenue to improve the material, Divya made it possible for me to work with Shobana Srinivasan and Gryffin Winkler, two editors who provided immense assistance during the writing process. Next, I would like to thank my supervisor, Prof. Patrick Wamuyu; my mentor, Paul Bombo; my boss, Geert van Bommel; and my colleagues at MG Lotus Ltd— Dylan, Jesse, Harro, Wouter, Manon, and Davor—for inspiring confidence in me to embark on a rigorous writing journey. Finally, I would like to extend my sincere, profuse thanks to my family for their unwavering support. To my parents, Bernadette Ocaya and the deceased Prof. Bruno Ocaya, I am forever grateful for all that you have done to nurture my interests in software engineering. From purchasing my first computer to paying for my education, the feats of your parenting have conditioned me to write this book I believe will prove helpful to those who read it. To my sisters, Frances, Consolate, and Faith, thank you for catalyzing writing efforts and, in particular, for spurring me on when I needed a boost. v
Page
6
Contents 1 An Introduction to Functional Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 Defining Functional Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Functional Programming Is Declarative and Imperative . . . . . . . . . . . . . 2 1.3 History of Functional Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.4 Functional Programming and PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.5 Functional Programming Lightens Cognitive Load . . . . . . . . . . . . . . . . . . 7 2 Functional Programming Core Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1 The Lambda Calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2.2 Functions in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.1 Functional Programming and Object Orientation . . . . . . . . . . . . 14 2.3 Pure Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.3.1 Side Causes and Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.3.2 Referential Transparency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.4 Immutability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.4.1 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.4.2 Persistent Data Structures. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3 Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.1 The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.2 Traditional Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3.3 Point-Free Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.4 Higher-Order Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.5 Currying. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.6 Partial Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.7 Map, Filter, and Fold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.7.1 Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.7.2 Filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.7.3 Fold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 4 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.1 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 vii
Page
7
viii Contents 4.2 Callbacks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.3 Default Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.4 Error Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.5 Composable try/catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.6 Sum Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.6.1 Maybe. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.6.2 Either . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 4.6.3 Promises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 5 Functors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.1 Thinking in Terms of Functors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 5.2 Category Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.2.1 Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 5.2.2 Identity. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 5.2.3 Functors in Category Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 5.3 Functors in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 5.3.1 Functors Are Type Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 5.3.2 Functor Laws in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 5.4 Monads. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 5.4.1 Natural Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 5.4.2 Monads and Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 5.4.3 Monad Laws in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 5.5 Practical Monads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 5.5.1 The I/O Monad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 5.5.2 The Reader Monad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 5.5.3 The State Monad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 5.5.4 The Writer Monad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 5.5.5 The List Monad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 6 Functional Programming and Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 6.1 PHP’s Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 6.2 Multithreading in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.2.1 Share Nothing with ext-pthreads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 6.2.2 CSP and ext-parallel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 6.3 Multiprocessing in PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 6.4 Message Brokerage with Evented I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 6.4.1 Evented I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 7 Additional Functional Programming Techniques . . . . . . . . . . . . . . . . . . . . . . . . 119 7.1 Lenses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 7.2 Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 7.3 Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 7.4 Property Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 8 A Simple Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 8.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 8.2 Wiring Things Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Page
8
Contents ix 8.3 Writing Registry Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 8.4 Writing REPL Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 8.5 Finishing the REPL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 A.1 Functional PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 A.2 Composing Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 A.3 Hoogle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 A.4 Bartosz Milewski’s Functional Programming Talks . . . . . . . . . . . . . . . . . . 158 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Page
9
About the Author Michael Bruno Lochemem an alum of the United States International University-Africa and a current MG Lotus employee, is a software engineer and technical writer from Kampala, Uganda. Michael is a Functional Programming advocate and an avid promoter of Systems Programming and evented I/O. He is proficient in PHP, C, and JavaScript and actively maintains open source software that aligns closely with his technical interests. His portfolio of open source contributions includes PHP libraries like bingo- functional and asyncify and language extensions like ext-mrloop, ext-trie, and ext-picohttpparser. Michael likes to publish articles that topically align with his interests on his blog hosted on Medium. He is a fan of the Miami Heat, Miami Dolphins, and FC Bayern Munich and plays basketball when he is not sitting at his desk. xi
Page
10
About the Technical Reviewer Sri Manikanta Palakollu is an accomplished software developer with five years of distinguished experience. He has demonstrated exceptional expertise across a diverse range of cutting-edge technologies, including Java, AEM, Python, Spring, Microservices, C++, C, JavaScript, TypeScript, MERN, databases, AI, and System Design. Beyond his exceptional technical capabilities, Sri Manikanta is also a prolific and acclaimed writer. He has authored numerous insightful articles on influential topics such as artificial intelligence, machine learning, programming, data science, and cybersecurity. His work has been featured on prestigious platforms, including Medium, HackerNoon, and Analytics Vidhya. Furthermore, Sri Manikanta has contributed his technical expertise to several esteemed publications from renowned publishers such as Packt and Apress, including his own authored book, Practical System Programming with C. In addition to his distinguished writing accomplishments, Sri Manikanta has showcased his expertise and creativity by winning a prestigious national-level hackathon. He also maintains an active involvement in numerous open source projects, demonstrating his passion for innovation and problem-solving. As a committed mentor, Sri Manikanta has guided over 5,000 students through coding hackathons organized by both national and international institutions and organizations. xiii
Page
11
Introduction Functional Programming has long been a staple of modern computing. Since the advent of Lisp in 1960, on the premise of achieving machine intelligence via a computationally idiomatic encoding of the Lambda Calculus, the paradigm has undergone a non-monotonic evolution. Initially a darling of the mainstream, the paradigm has been forced outside its confines into the world of academia and has recently re-emerged in the zeitgeist as a wholesome approach to writing computer programs. What makes Functional Programming especially compelling is its emphasis on solving problems via composition, a process defined by the ability to parameterize aspects of answers and combine the functions created on parameterization. The average PHP developer is likely to have encountered Functional Program- ming to the extent of deliberately or otherwise writing pure functions, applying some variation of composition, or invoking some nuanced paradigmatic technique. This book, targeted at professionals and hobbyists with intermediate- to advanced- level proficiency in PHP interested in Functional Programming, is a distillation of essential paradigmatic concepts that satiates the curiosity of those in the aforemen- tioned skill categories, who, whether knowingly or not, might have dabbled in some Functional Programming before or are at least aware of its existence, but, more importantly, intrigued by its viability in PHP. It provides a ground-up instruction in expressing PHP programs as function composites by discussing the rudiments of Functional Programming, pure functions, immutability, and composition, before expositing more advanced paradigmatic patterns such as currying, functors, and Communicating Sequential Processes (CSP). In reading this book, you will likely discover certain things about Functional Programming, as interspersed in its contents are refutations of falsehoods about the paradigm, descriptions of the origins of commonplace programming concepts that accurately portray it as a wellspring of popularized knowledge, and digestible breakdowns of paradigmatic jargon and techniques that might seem difficult to comprehend. It is my hope that you find the material you are about to peruse edifying and can, upon completion, espouse the Dao of Functional Programming— composition. xv
Page
12
Chapter 1 An Introduction to Functional Programming 1.1 Defining Functional Programming The process of software development is typified by the practice of breaking down larger problems into smaller ones. The result of this approach is often the creation of a solution—an application—by stitching together encodings of ideas that, in isolation, solve one of either a single problem or a subset of problems. Stitching together is, in this case, synonymous with defining rules, representing those rules in isolated, callable units, and applying those rules. Rules are explicit statements of intent. They are a means by which to define a task to complete and nothing more. Herein lies the definition of Functional Programming. Functional Programming is an approach to building applications that is centered around composing pure functions (enforcements of rules) unburdened by the vagueness of side effects and side causes. Side effects and side causes are (ever- present) vectors that can, if unconstrained, invalidate rules and thence render functions impure. More on this later. In drafting rules, writing, and subsequently invoking the functions that enforce their boundaries, the principle of abstraction takes center stage. Functions abstract rules, but more specifically, the actions undertaken to effect them: they tidy away rule-specific actions that are typically combinations of effectful expressions. Consider the problem of adding two integers. The rule, computing the sum of two integers, can be abstracted into the signature of an arbitrarily named function that takes two arguments as in the example to follow. © The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2026 M. B. Lochemem, Functional Programming in PHP, https://doi.org/10.1007/979-8-8688-2468-5_1 1
Page
13
2 1 An Introduction to Functional Programming A simple function to compute the sum of two numbers function add(int $x, int $y): int { return $x + $y; } echo add(1, 7); The function “add” contains the semantics of the desired summation—a simple expression that effects the sum of two operands, the two arguments named “x” and “y.” Beyond the rule and its implementation, the invocation of the “add” function represents the rule in effect. The expectation is such that the sum of 1 and 7, as computed by “add,” yields 8 and will do so every time the arguments are 1 and 7. Because there are no vectors that could change the “add” function’s behavior, the rule it is based on is never undermined, and thus, the function’s purity is upheld. Such is the nature of Functional Programming. •> The Real World Functions like those featured in the previous snippet are ideal and, sadly, fail to fully represent the real world where the rule-breaking vectors inherent to network and file Input/Output (I/O) feature prominently. They do, however, help communicate paradigmatic principles and the possible outcomes achievable with techniques yet to be discussed in future sections of the book. 1.2 Functional Programming Is Declarative and Imperative Thus far, decent ground has been covered in regard to describing the declarative nature of Functional Programming. For a syntax to be considered declarative, it has to condition in its users a willingness to describe computations abstractly. In Functional Programming, this abstractness manifests not only in the tidying away of operations but also in the mental real estate of the programmer, as a pronounced focus on the intent defined in rules. No artifact embodies the ideals of declarative programming better than expressions. Expressions are effectful statements through which to apply rules. They often consist of some combination of function calls and operations with one or several operands and are yet another fixture in day-to-day programming.
Page
14
1.2 Functional Programming Is Declarative and Imperative 3 An assortment of valid expressions in PHP 2 * 2; \array_filter( \range(1, 5), fn (int $x): bool => $x % 2 === 0, ’foo’ . ’-bar’; \SplFixedArray::fromArray( [ ’foo’, ’bar’, ’qux’, The results of expressions like those shown in the snippet above can be stored in memory in such a way as to render them reusable throughout an accessible scope of an application—via an assignment operation. In fact, this is another practice that is commonplace in everyday programming—particularly of the procedural kind. With procedural programming, every result is holstered in memory for often near- immediate or sometimes future use. Consider the snippet below. A program that demonstrates a procedural approach to adding numbers $x = 1 + 7; $y = $x + 3; $z = $y + 2; echo $z; There are, in the example, three successive addition expressions that each effect the addition rule that informed the creation of the “add” function from the previous segment. Each result, bar the last, is used in a subsequent expression, and every binding holsters itself in the programmer’s mental real estate. With calls to a pure function like the one from the previous segment, the successive bindings can effectively be reduced to a single one. In exploring this, it is possible to chain rules and, thus, the functions that enforce them—as in the modifications below.
Page
15
4 1 An Introduction to Functional Programming A demonstration of the replacement of imperative addition with function application $z = add( add( add(1, 7), // $x 3, // $y 2, // $z echo $z; The three bindings from earlier do not exist in the snippet above. They have effectively been replaced with a composition of calls to the pure “add” function. The replacement does not alter the imperative nature of the program but rather refines it with composition. Function chains in which the output of one call to a pure function is propagated as the input of the one that follows it reduce the likelihood of the impurities (vectors) in certain expressions compounding over sequenced assignments. It is, therefore, safe to assert that Functional Programming conditions its practitioners to engage in “safe,” vector-controlled, rule-respecting imperative- style development. 1.3 History of Functional Programming The roots of Functional Programming are traceable to the seminal works of Alonzo Church and Alan Turing. Church advanced the Lambda Calculus, a mathematical notation that emphasizes using functions as rules for turning inputs into outputs (more on this later), in the 1930s. His doctoral student, Turing, shortly after, put forward the idea of a Universal Machine, an emulation of a device capable of making axiomatic computations—one capable of solving problems in discrete steps (algorithms). While Church’s Lambda Calculus provided a syntax for the abstraction that characterizes Functional Programming, Turing’s hypothesis laid out the fundamental means of designing and executing computer programs. Almost two decades after the inception of the Lambda Calculus and Universal Turing Machine emerged the first real Functional Programming language—Lisp. The world into which Lisp was introduced was one primed for modern computing. By the time Lisp was first released for the IBM 704 in 1958, the transistor and von Neumann stored-program concept had already taken a foothold in computing. By creating Lisp, John McCarthy realized a syntax that resembles the notation in Church’s Lambda Calculus and adheres to the computation-by-algorithm rubric in Turing’s Universal Machine. McCarthy’s work on Lisp also pioneered ideas such as dynamic binding, garbage collection, recursion, and higher-order functions—
Page
16
1.4 Functional Programming and PHP 5 ideas that characterize the complexion of modern computer programming today. In offshoots like Scheme, Clojure, Janet, and Phel (more on this later), Lisp lives on to this day. In the 1970s, Functional Programming, and, in particular, the Lisp variants of that time, began to cede popularity to object-oriented and procedural strategies. Smalltalk, one of two major competitors in that decade, was created in 1972 in Palo Alto. With its inception came an ideology centered around using objects and the methods defined in them to shuttle data in applications. The ideals of Alan Kay, the then leader of the Xerox Palo Alto Research Center (PARC) team that created Smalltalk, were, in reality, not completely divorced from those of Church and Turing, but nevertheless established the foundations of Object-Oriented Programming as we know it today. C, the other major competitor, was conceived in 1978 after two failures— Multics and the B programming language. The former was an attempt at creating an Operating System (OS) that was ultimately derailed by its lead engineers—Dennis Ritchie and Ken Thompson—failing to optimize its kernel for the hardware it was intended to run on. The latter, a creation of Thompson’s, was characterized by a suboptimal compiler and an incomplete type system. The version of C that became a mainstay in computer programming overcame the challenges in the projects that directly preceded it and offered a mostly imperative approach to building computer programs. The creation of Haskell in the late 1980s by a team of academics did little to stem the momentous tide of alternative programming approaches, as the paradigm was pushed further to the periphery of mainstream programming in the decades that ensued. The recent revival of Functional Programming began around the time paradigm constructs started to feature prominently in large codebases of popular software. Around the 2010s, the first real hints of a revival came in the form of Twitter shipping Scala and Clojure rewrites of their backend code. Scala and Clojure were, at the time, fairly new additions to the Java Virtual Machine (JVM) and offered some real upside for the company’s scaling efforts despite having small communities at the moment of first adoption. Twitter’s adoption of Functional Programming tooling was soon followed by Facebook’s back-to-back rollouts of Flow, an OCaml-powered type checker for JavaScript, and Haxl, a spam filter written in Haskell, in 2014 and 2015, respectively. The goodwill earned through the successes of these endeavors prompted industry-wide reacceptance of Functional Programming ideas and, thus, a re-entry of those ideas into the mainstream. 1.4 Functional Programming and PHP PHP was developed in 1995 at a time when Functional Programming occupied the ideological territory on the periphery of mainstream computer programming. Perl was the darling of scripting languages during this period and was one of many key influences on the earliest designs of the PHP language. Baked into early
Page
17
6 1 An Introduction to Functional Programming PHP were Perl’s dollar-sign-prefixed variables, regular expressions, and Common Gateway Interface (CGI) bindings. It is worth noting that these features are still fixtures of modern PHP. The language, in its infancy, was a neat wrapper around Perl and C whose purpose was simplifying web page content rendering while simultaneously providing a small performance benefit. Compounding functions into full-on applications in PHP’s earliest versions was a strenuous task as every function, except those provided out of the box, had to be written in C, added to a symbol table, registered as a grammatical tool in a parser-generator file, and compiled so as to be operationalized for calls in the language userspace. Working Functional Programming patterns like the ones you will see later in this book into projects written in PHP I, or its successor, PHP/FI (Form Interpreter), was discernably difficult when PHP was freshly incepted: after all, the language was, at this stage, almost exclusively useful for small projects. In reaching out to Rasmus Lerdorf in the late 1990s via mailing list to discuss improvements to the PHP/FI project, Zeev Suraski and Andi Gutmans began the work of rewriting the PHP interpreter to offer more out-of-the-box userspace features. First worked into PHP 3 and then refined in PHP 4, the Zend engine, effectively the revamped interpreter created by the two Israeli programmers in consort with Mr. Lerdorf, ushered in artifacts that feature prominently in appli- cations written in modern variants of the language. With the engine came a slate of artifacts like classes, namespaces, constants, and user-defined and anonymous functions that are all relevant to Functional Programming. In the early 2000s when PHP 4 was released, Object Orientation was the eminent paradigm. C++, Java, and C#, all multipurpose languages that exemplify the principles of Object-Oriented Programming, were ever-present across the realms of Systems Programming, web development, and desktop application development. Naturally, PHP took on and still retains a bend toward Object Orientation. The versions of PHP that have followed the monumental fourth one have all shipped some combination of new functions, deprecations, and general engine performance improvements. The language artifacts well suited to the needs of Functional Programming have remained mostly intact through PHP’s continued evolution. Functions have retained their first-class citizenry through most of the newer versions of PHP and, despite the ecosystem’s pronounced emphasis on pat- terns centered around SOLID principles, have also mostly subtly retained their latent potential for use in Functional Programming. PHP, in its current state, complements its core of Functional Programming artifacts with interpreter enhancements, such as arrow functions, a match operator, and, soon, pipe syntax. At present, PHP is just as equipped to enable Functional Programming as any other programming language whose core fundamentals have been adapted to advance its ethos of encoding rules and composing the pure functions that best enforce their dictates.
Page
18
1.5 Functional Programming Lightens Cognitive Load 7 1.5 Functional Programming Lightens Cognitive Load It would be remiss to discuss Functional Programming’s rationale and origins with little mention of the cognitive benefit that accrues to those who adopt its principles. Abstraction and rule-based composition lighten the strain on the working memory of programmers. Computer programming, like a lot of tasks that require one to attentively reason about concepts—solving a series of mathematical equations, writing a paper, and whatnot—has the capacity to overwhelm one’s working memory. The limitation of working memory is such that its information space, referred to as the mental real estate earlier in this chapter, is only accommodative of about seven or so entries—quanta. This real estate gets new tenancy every 30 seconds or so and, thus, requires additional mental effort to retain information a little longer than its lifespan. Composing pure functions helps programmers achieve valuable mental real estate savings. If each variable in a program can be thought of as occupying a quantum of information in the brain’s working memory information space, programs written in such a way as to rely exclusively on the effects of each assignment put significant strain on the finite mental real estate of a programmer. Think back to the imperative sequential addition problem from earlier in the text. The summation results assigned to each variable $x, $y, and $z each registered an entry in working memory. In eliminating $x and $y via composition, albeit with a regular chain of function calls, the strain on working memory was somewhat alleviated: the slots reserved for $x and $y were vacated. Functional Programming prescribes the expression of intent in as concise a manner as possible. While assignment is not a bad thing in and of itself, is generally unavoidable, and can be managed even under strenuous effect workloads, it is best reserved for operations that require a longer presence in an algorithm and, thus, a longer lifespan in working memory. The downstream effect of enforcing rules via functions that neatly tidy away effects, composed with terse assignments where necessary, is a lower Signal-to-Noise ratio. If the ability to create programs from well-formed artifacts that can fit well together and can be comprehended in isolation is a quality that best exemplifies the signal and the analog of the noise is a combination of all the stressors on the conciseness of a program, then composing functions in such a way as to encode all the useful rule rubric without introducing more artifact bindings than required produces a clearer signal. This segment concludes the introductory chapter of the book. The next chapter will flesh out the fundamentals of the Functional Programming paradigm, expanding on the ideas of function purity, which was briefly discussed earlier, as well as referential transparency, the standard by which purity is measured, and immutability, a quality that defines the rigidity of the paradigm.
Page
19
Chapter 2 Functional Programming Core Concepts 2.1 The Lambda Calculus In the beginning, there was the Lambda Calculus. Alonzo Church devised, in the 1930s, a concise syntax for function application that would go on to formalize the fundamental ideas of the Functional Programming paradigm. The Lambda Calculus, like its offshoots, is a formal syntax complete with variables, expressions, and, most importantly, functions. It is a means of solving problems through a two-step function application process that starts with the substitution of arguments and ends in the evaluation of the expressions to which the arguments are applied. Imagine being asked to calculate the circumference of a circle with a radius of 5 units. Solving such a problem with the Lambda Calculus means creating a function that abstracts a suitable expression into which arbitrary arguments can be plugged with every invocation. A valid notational representation of a function with which to solve the circumference problem is as follows. .CIRCUMFERENCE = λr[2πr] (2.1) The lambda (λ.) in the notation above is the starting point of any encoding in the Lambda Calculus. It is instructive insofar as signaling the substitutability of all the variables that follow it: those local to the expression in the function and thence referred to as “bound.” The λ. effectively denotes a λ.-term that signals that the expression that follows it—that in the square brackets—is ready to be applied to values assignable to all (local) “bound” variables when its host function is called. As far as the circumference encoding is concerned, the local variable is r , and the evaluable expression is 2πr . In following through with the example, the computational steps shown below should yield a valid circumference. .(CIRCUMFERENCE)5 = (λr[2πr])5 2 × π × 5. (2.2) © The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2026 M. B. Lochemem, Functional Programming in PHP, https://doi.org/10.1007/979-8-8688-2468-5_2 9
Page
20
10 2 Functional Programming Core Concepts = 10π . (2.3) = approx.31.4159 (2.4) The calculation shown above is such that every occurrence of r is replaced with the value 5 before the arithmetic is effected, and the result is ultimately computed. The two-step function application process shown above is the β .-conversion (or β .- reduction), essentially the Golden Rule of the Lambda Calculus, and the gateway to function composition—as you will see later in the book. All computations in the Lambda Calculus, and, by extension, Functional Programming, are essentially abstractions of rules encoded as functions over relevant values per the principle of the β .-conversion, the identity for which appears below. .(λx[M])N M[x := N ] (2.5) Given an expression M , a variable x, and an argument N , all occurrences of x in the expression M need be swapped with the value assignable to N . Such is the interpretation of the β .-conversion. Because of this rule orientation, the Lambda Calculus allows for distinct forms of otherwise equivalent functions to exist. What this means is that notationally, functions that are semantically different but implement the same rule are considered distinct—like synonyms in the English language. If the circumference function from before were to be rewritten as in the snippet below, the resultant function, and, thence, the resultant substitution on application, would more or less produce the same result, but retain distinguishability. .(CIRCUMFERENCE)5 = (λr[πr + πr])5 π × 5 + π × 5. (2.6) = approx.31.4159 (2.7) The principle shown above is known as hyperintensionality. Hyperintensional- ity implies that multiple variants of a rule, each with a subtle, distinctive quality, are permissible. In practice, the slight contextual differences between functions designed to implement the same rule often prove consequential. Imagine two variants of a JSON decoder—one that implements a linear parser and another that relies on Single Instruction, Multiple Data (SIMD) parsing routines. The latter is temporally more efficient than the former, but nevertheless converts a JSON string to a hashtable. Now that it is clear how functions are created and used in the Lambda Calculus, the next step is to evaluate the varieties of functions available in PHP and the modalities of function use in the language.