Key Takeaways
- Functional programming treats computation as the evaluation of mathematical functions and avoids state and mutable data, treating functions as first-class citizens. This means functions can be used in the same way as values in imperative programming.
- Key concepts of functional programming include immutability (values of a variable cannot be changed once defined), recursion (often used due to immutability), pure functions (those without side effects), and higher order functions (those that can take functions as arguments and return a function as a result).
- Functional programming can lead to cleaner, more readable code, encouraging safe programming by avoiding state and mutable data. It can also help you focus on what you want to achieve instead of managing incidentals in the process.
- Despite its advantages, functional programming has a steep learning curve for those trained in an imperative manner. Some of the benefits traditionally associated with functional programming are not applicable to PHP as it’s not designed to be a functional programming language. It also might not always be the most efficient way to write programs.
Important Concepts of Functional Programming
Starting with the jargon, Wikipedia defines functional programming as “a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data.” In functional programming, functions are treated as first-class citizens, whereas in imperative programming we are mostly concerned with the data and the steps to alter it to reach the desired result. When we say functions are first-class, it means we can use functions just as we use values in imperative programming. They can be passed as an argument to a function, defined inside another function, and can even be returned as a result. In other words, “functions are values”. We’ll come back to this again later, but there are many other important concepts of functional programming. To mention a few:Immutability
Immutability is the behavior that a value of a variable cannot be changed once it is defined. Different languages have different ways of achieving this; in PHP, for instance, the only way to make a variable immutable is to define it as a constant.Recursion
Recursion is also very prominent in functional programming. In imperative programming, we can use looping constructs likefor
and foreach
when we need to manipulate collections or arrays, walking through each element and keeping a temporary variable to hold the current value. But because of immutability, this approach is not possible in functional programming. Recurssion is the answer because such book keeping is done implicitly with the call stack.
Suppose we want to write a function to find the sum of all elements in an array (forget that array_sum()
exists for the time being). In a functional style, we would write:
<?php
function sum($array) {
if (empty($array))
return 0;
else
return $array[0] + sum(array_slice($array, 1));
}
$total = sum(array(1, 2, 3)); // 6
An empty list will return 0, which is our base condition. For an array with more than one value, it will return the results of adding the first element with the recursive sum of all other elements.
Pure Functions and Referential Transparency
A function is said to be free from side effects if it does not change the value of an object outside itself, such as a global or static variable, and does not have any I/O effects like writing into file, database, and so on. Such functions are otherwise called pure functions. The output of a pure function will always be the same for a given set of arguments, which leads to another property called referential transparency. When a function is referentially transparent, we can replace that function with its value without affecting the behavior of the program. All mathematical functions are pure functions, whereas date functions,rand()
, etc. are impure.
Higher Order Functions
The concepts above can be achieved in almost any programming language, but first class functions and higher order functions are the two most distinguishing features of functional programming. I explained that first class functions means that functions can be treated as values. Higher order functions are functions that can take functions as arguments and can return a function as their result. Two important features were added relatively recently which enabled us to write higher order functions in PHP: lambdas and closures.Lambda Functions
A lambda function (also known as anonymous function) is nothing but a function that has no name. When we define an anonymous function, a reference to the function is returned which is stored in a variable for later use. We use this variable to call the function whenever it’s needed. This concept has been adopted in many different languages. In fact, you’re probably using lambda functions in your day-to-day JavaScript programming, passing them as callback functions for different user interactions and Ajax calls.$("#myButton").click(function () {
// do something
});
This piece of code is so simple and easy to understand, which might make us forget its functional aspect.
PHP introduced this awesome feature in version 5.3, which lets us write PHP code in a similar fashion:
<?php
$square = function ($arg) {
return $arg * $arg;
};
$value = $square(2); // 4
When talking about functions, and anonymous functions in particular, its important to understand how variable scope is handled. JavaScript, for example, allows you to access a variable from an outer scope inside the lambda, whereas PHP does not. Inside the lambda is its own scope, just as with regular PHP functions.
Closures
Sometimes you’ll want to reference a variable from the parent scope inside your function. Closures are similar to lambda functions with the minor difference that you can access variables from an outer scope. We can use “reach out” and bind an outer variable using PHP’suse
keyword, also introduced in PHP 5.3.
<?php
$rate = .12;
$findInterest = function ($value) use ($rate) {
return $value * $rate;
};
$interest = $findInterest(100);
In this case we don’t pass the interest rate each time we call the function. Instead, we’ve defined it outside and made it available inside the function with the use
keyword.
Partial Functions and Currying
A partial function, simply put, is a function created from an existing function by partially applying its arguments. You only need to pass the remaining arguments when you call the created function. We can create partial functions in PHP with the use of closures. Here’s an example to find the volume of a box given its length, width and height. All arguments are optional; if you don’t supply all of the arguments, the function will return another function to accept the necessary values that remain.<?php
$volume = function ($length = 0, $width = 0, $height = 0) use (&$volume) {
$args = func_get_args();
$numArgs = func_num_args();
if ($numArgs == 3) {
return $length * $width * $height;
}
else if ($numArgs < 3) {
return function() use(&$volume, $args) {
$newArgs = array_merge($args, func_get_args());
return call_user_func_array($volume, $newArgs);
};
}
else {
throw new BadFunctionCallException("Too many arguments");
}
};
All of the parameters are optional. First a check is made to determine whether the caller passed all arguments. In that case, we can directly return the volume by multiplying length, width and height. If the number of arguments is less than the parameters, a new function is returned to find the volume “pre-seeded” with the given arguments.
Now suppose that most of the time we’re finding the volume of box with a fixed length, say 10. This can be easily done by passing 10 as the first argument, or we could create the partial function by fixing 10 as the first argument and then only ask for the remaining values.
<?php
$standardVolume = $volume(10);
$vol = $standardVolume(5, 5); // 250
Currying is a special case of partial functions where you convert a function that takes multiple arguments into to multiple functions that will each take a single argument. For example, something like f(x,y,z) to f(x)(y)(z) (although PHP syntax doesn’t allow nesting of function calls like this). Timothy Boronczyk has written an excellent article on currying with a practical example if you’re interested in seeing more.
Advantages and Disadvantages
There are many practical uses of functional programming features in PHP. For instance, lambda functions are widely used when working with callbacks. Using the Slim framework, for example, you can define a route like this:<?php
$app = new SlimSlim();
$app->get("/home", function () {
// show home page
});
Slim invokes the callback function when the request URL matches this route. Vance Lucas wrote about some other interesting use cases of Lambda functions a while back.
Safe programming is encouraged by avoiding state and mutable data. In functional programming you should write functions that do exactly one thing each and do not cause any side effects. The paradigm’s emphasis on modularity and conciseness of functions can make its easier to reason about your program in terms of different, small sub programs as well.
Functional programming can also help you write code that focuses what you want to achieve instead of explicitly managing the incidentals in the process (compare recursion with having to manage loop counter variables).
But keep in mind however that some of the advantages traditionally associated with functional programming are not applicable to PHP as it’s not designed to be a functional programming language. For example, side-effect-free functions lend well to parallel processing, but PHP scripts are not run in this manner.
It’s not always easy to calculate the cost of recursion and lazy functions, either, and there can be significant performance issues due to the internal overhead. Sometimes it makes more sense to write programs in terms of mutability for better efficiency.
Perhaps the biggest disadvantage of functional programming is its steep learning curve for those trained in an imperative manner. But over all, functional programming is interesting, and learning it will give you the tools to think about old problems in a new light, helping you to grow as a programmer. It’s not a one-size fits all solution, but it can be applied as appropriate for cleaner, more eloquent PHP code.
Summary
Functional programming is more than just a programming paradigm; it’s a way of thinking and reasoning about your program. If you can think functionally, you can do functional programming in almost any language. In this article we discussed the basics of functional programming, leveraging features of PHP to write provide their examples. Although, the example given in this article may not be practically useful to you, you’ll find many situations where the functional style can significantly improve the quality of code you are writing. Try to find such cases, think functionally, and have fun! Image via FotoliaFrequently Asked Questions about Functional Programming in PHP
What is the main difference between functional programming and object-oriented programming in PHP?
Functional programming and object-oriented programming are two different paradigms used in PHP. The main difference lies in how they manage state and data. In functional programming, functions are first-class citizens and there is no concept of state. This means that given the same input, a function will always produce the same output. On the other hand, object-oriented programming revolves around objects and their interactions, which can maintain state and change over time. This can lead to different outputs, even with the same input.
How can I start with functional programming in PHP?
To start with functional programming in PHP, you need to understand the basic concepts such as pure functions, immutability, and higher-order functions. You can then start writing functions that don’t change state and don’t produce side effects. PHP has built-in functions that support functional programming such as array_map, array_filter, and array_reduce. You can also use libraries like Laravel collections that provide a fluent, convenient wrapper for working with arrays of data.
What are the benefits of functional programming in PHP?
Functional programming in PHP can lead to cleaner, more readable code. It can help you avoid common programming issues like side effects and state changes, which can make your code more predictable and easier to test. Functional programming can also lead to more modular code, as functions can be easily composed and reused.
Are there any limitations or challenges in using functional programming in PHP?
While functional programming has its benefits, it also has its challenges. PHP was not originally designed with functional programming in mind, so some features may not be as robust or efficient as in languages that are designed for functional programming. Additionally, functional programming requires a different mindset and can have a steep learning curve for developers used to imperative or object-oriented programming.
Can I mix functional programming and object-oriented programming in PHP?
Yes, PHP is a multi-paradigm language, which means you can mix different programming styles. You can use object-oriented programming for parts of your application that benefit from state and behavior, and use functional programming for parts that benefit from stateless, side-effect-free functions. This can give you the flexibility to choose the best approach for each part of your application.
How does functional programming affect performance in PHP?
The impact of functional programming on performance in PHP can vary. In some cases, functional programming can lead to more efficient code, as it avoids state changes and side effects. However, in other cases, it can be less efficient, as it often involves creating new objects instead of modifying existing ones. It’s important to profile and test your code to ensure it meets your performance requirements.
What are some good resources for learning functional programming in PHP?
There are many resources available for learning functional programming in PHP. Some good starting points include the PHP manual, which has a section on functional programming, and online tutorials and articles. There are also several books available on the subject, such as “Functional Programming in PHP” by Gilles Crettenand.
Can I use functional programming in PHP for web development?
Yes, you can use functional programming in PHP for web development. Functional programming can help you write cleaner, more modular code, which can be beneficial in a web development context. However, keep in mind that PHP is a multi-paradigm language, so you can also use other programming styles like object-oriented programming.
How does functional programming in PHP handle error handling?
In functional programming, error handling is often done through the use of monads, which are a type of data structure that can represent computations instead of values. In PHP, you can use the Maybe monad for error handling. This allows you to chain operations together, and if any operation fails, the rest of the chain is skipped.
Is functional programming in PHP suitable for large-scale applications?
Functional programming can be used in large-scale applications, but it depends on the specific requirements of the application. Functional programming can lead to cleaner, more modular code, which can be beneficial in a large-scale context. However, it can also be less efficient in some cases, so it’s important to consider the trade-offs.
Shameer is a passionate programmer and open-source enthusiast from Kerala, India. He has experience in web development using Scala, PHP, Ruby, MySQL, and JavaScript. While not working, Shameer spends his time coding personal projects, learning, watching screen casts, blogging, etc. His specific areas of interest include cloud computing, and system and database administration.