7 kyu

PHP Functions - Anonymous Functions (aka Closures)

453 of 454donaldsebleung

Description:

PHP Functions - Anonymous Functions (aka Closures)

About this Kata Series

"PHP Functions" is a Kata Series authored by donaldsebleung which focuses on the perks and interesting features of PHP functions. It is un-numbered which means that the Kata in this Series is not progressive - one kata in this Series does not necessarily depend on another. This means that as long as you know how to write "Hello World" level programs in PHP, you will probably find any Kata in this Series easy to pick up and complete.

There is, however, one main prerequisite. You must be sufficiently familiar with primitive data types in PHP (strings, booleans, floats, integers) and what they mean. You must also have a basic understanding of how to define a simple function in PHP that may or may not receive a fixed number of arguments. A good indicator that you are ready for any Kata in this Series is if you are able to complete Multiply (8kyu) in PHP without looking at external resources in the process. If you are unable to complete that Kata without researching PHP function syntax then you may have to practice with basic PHP functions until you are familiar with them before continuing on this Kata series.

Certain Kata in this Series may have additional prerequisites. If that is the case, the extra prerequisites will be listed under a Level 2 Heading called Prerequisites in said Kata. Additionally, if a certain Kata in this Series requires a thorough understanding of PHP, the kata may be labelled as [Advanced].

Lesson

Prior to PHP 5.3.x, variables and functions were two complete separate things. This meant that functions could not be assigned to variables:

// PHP < 5.3.x ONLY
$closure = function ($a, $b) {
  /* Will this work in PHP < 5.3.x? */
};
// An error is produced, probably a fatal error or syntax error (PHP < 5.3.x ONLY)

If a function had to receive "another function" as one of its arguments and execute it, the only way was by variable functions (whose name I find quite misleading). The whole idea of a variable function (which is NOT a closure) is if there is a named function defined some_function and a variable $var_func contains the name of that function as a string "some_function", then said function will be executed if parentheses are appended to the variable, like such:

function some_function(/* parameters */) {
  /* some code */
}

$var_func = 'some_function';
$var_func(/* arguments */); // `some_function` is executed with the provided arguments

This was sometimes required by some built-in functions (such as array functions):

function multiply($a, $b) {
  // A named function called "multiply" which multiplies two numbers together
  return $a * $b;
}

$my_array = array(1, 2, 3, 4, 5);
// We want to compute the product of all the items in $my_array
echo array_reduce($my_array, 'multiply', 1); // Reduces the array into a single value using external function "multiply"

However, in the example above, you may have noticed that the named function multiply() was explicitly defined at the start of the script just to be used exactly once to operate on an array! That's hardly efficient, is it?

Fortunately, PHP 5.3.0 introduced a new feature called anonymous functions (or more commonly known as closures). An anonymous function is basically an unnamed function that can be directly assigned to a variable. For example:

$multiply = function ($a, $b) {
  // An anonymous function (aka closure)!
  return $a * $b;
};
$multiply(3, 5); // 15
$multiply(13, 14); // 182

In terms of syntax and behaviour, closures are pretty much identical to named functions. However, please note that when assigning a closure to a variable, the trailing semicolon is required (just like when assigning other values to a variable); otherwise, it will result in a syntax error.

This also means that you can directly pass a closure into a function that requires it as of PHP 5.3.0 instead of passing in the name of a named function:

$my_array = array(1, 2, 3, 4, 5);
echo array_reduce($my_array, function ($a, $b) {return $a * $b;}, 1); // 120
// See?  Much cleaner code :)

The introduction of this feature also means that a function can now return another function in PHP but we will not cover that in this lesson.

Task

Note: The lesson provided in this Kata is designed to teach you most, if not all, of the key concepts required to complete the Task in this Kata. However, if in doubt, you are strongly encouraged to conduct your own research.

Define the following closures and store them into the variables as specified.

  1. $hello_world - This variable should be assigned a closure that receives no arguments and returns the string "Hello World"
  2. $person_description - This variable should be assigned a closure that receives three arguments in the order $name, $age and $occupation. It should return a string of the format "NAME_HERE is AGE_HERE years old and currently works as a(n) OCCUPATION_HERE" (N.B. The "a(n)" part of the string is literal - your function does not need to format the string according to whether the occupation starts with a vowel or a consonant)

Switch to another Kata in this Series

Go

You May Also Like

Fundamentals
Tutorials

Stats:

CreatedSep 10, 2016
PublishedSep 10, 2016
Warriors Trained724
Total Skips84
Total Code Submissions779
Total Times Completed454
PHP Completions453
Total Stars9
% of votes with a positive feedback rating88% of 103
Total "Very Satisfied" Votes79
Total "Somewhat Satisfied" Votes23
Total "Not Satisfied" Votes1
Total Rank Assessments7
Average Assessed Rank
7 kyu
Highest Assessed Rank
7 kyu
Lowest Assessed Rank
8 kyu
Ad
Contributors
  • donaldsebleung Avatar
  • smile67 Avatar
Ad