How to use functional programming in PHP. PHP is not a functional programming language like Lisp. More, PHP is suitable for writing code in the C style. PHP does not have the "function" type. that is to say, the function cannot directly use the variable PHP instead of a functional programming language like Lisp, PHP is suitable for writing code in the C style. PHP does not have the "function" type. that is to say, the function cannot be passed directly using variables. For example, the following code:
Function test () {echo "welcome to bkjia.com" ;}$ test1 = test; echo gettype ($ test1); // output string
PHP parses the above code in this way.
// If a bare string does not start with the $ character, it is treated as a constant. // PHP regards test as a constant, but the test is not a constant in the code, PHP then regards the constant name as its value $ test1 = test; // when PHP encounters an undefined constant, it regards it as a string value, as shown in the following var_dump (UNDEFINED_CONSTANT ); // output string (18) "UNDEFINED_CONSTANT"
This indicates that the function name in PHP will be treated as a string without calling (without parentheses.
Coincidentally, PHP uses a string name to dynamically call a function:
$ PhpInfo = 'phpinfo'; $ phpinfo (); // There is another way call_user_func ('phpinfo ');
In C language, you can pass a function as a parameter by pointing to a function pointer to implement advanced FP. in PHP, the function name is passed as a string, $ fname () is used to call a variable ($ fname is a string type variable whose value is the function name) or call_user_func. So here we will find the inconvenience caused by the implementation of functions in PHP, because the functions are passed and called through strings, therefore, the existence of two different functions with the same function name is not required. That is, all functions in PHP (the "function" mentioned here does not include methods) are global functions and cannot be redefined at runtime, because if you allow repeated function definitions (such as JavaScript), the following code will fail:
// For the first time, define the test1 function test1 () {return 123;} // assign the variable $ testFunction to the function name of test1 // In fact, this method is inefficient, so it is better to write: $ testFunction = 'test1'; $ testFunction = test1 ;//....... after several lines of code, // redefine test1 function test1 () {return 456;} // The output is different from the expected value, because the variable is only the name of the saved function // It is not really a reference to the function echo $ testFunction ();
Since all functions in PHP are global functions, function declarations cannot be nested (Closure ), before discussing Closure and Lambda in PHP, we should first discuss the methods in PHP (that is, functions that have been bound to a specified object or class ). First, create a simple class and output its static method to see what it is.
Class Demo {public static function test () {return 123 ;}} var_dump (Demo: test); // An error occurred at this step // because PHP is parsing Demo :: test will regard it as reading the static attribute of the Demo class // and this static attribute does not start with $, so it will be treated as a static constant (const) // if this constant does not exist, an error occurs.
What should I do if I want to dynamically call a class (or instance) method? First, let's look at a real example of a very simple Controller (of course the real Controller cannot be so simple)
Class Controller {public function login () {echo "Login" ;}public function home () {echo "Home" ;}public function logout () {echo "Logout !!! ";}}$ Action =$ _ GET ['action']; // The name of the method to be called is included in the action parameter. // then, you need to dynamically call the specified method Controller :: $ action (); // use this method, mainly because of the "variable" mechanism in PHP. // of course, check whether the class has this method, PHP Reflection mechanism can be used to detect $ reflectionClass = new ReflectionClass ('controller'); $ reflectionClass-> hasMethod ($ action ); // test whether a corresponding method exists. // test whether the method is static. $ reflectionMethod = $ reflectionClass-> getMethod ($ action); $ reflectionMethod-> isStatic (); // returns true if it is a static method.
In addition to the variable mechanism of PHP, you can also use the previous call_user_func function.
// Upload an array as the first parameter. The first element in the array is the class name, and the second element is the static method name call_user_func (array ('controller', $ action )); // If you want to pass a parameter to a method or function, you can append the parameter to function test ($ a, $ B) {echo $ a + $ B;} call_user_func ('test ', 123,456); // or use the call_user_func_array function call_user_func_array ('test', array (123,456) when the parameter is set )); // Before PHP 4.1, the call_user_method function and // call_user_method_array are used to call the object method, but they are not used anymore.
If you need to call the instance method
Class Demo {public function test () {echo "Instance Method" ;}}$ d = new Demo (); $ d-> $ action (); // or call call_user_func (array ($ d, $ action) in this way; // if the class Demo does not declare the constructor as private, you can still call the instance method call_user_func (array ('demo', $ action) without an instance ));
From the code above, we can see that the classes in PHP are also passed in the form of strings. Like the following code:
$ Class = Demo; echo gettype ($ class); // string // similar to the function, PHP regards Demo as a normal bare string.
In PHP 5.2.3, there is another syntax for calling static methods of classes in PHP.
//PHP 5.2.3 call_user_func('Demo::'.$action);
Starting with PHP 5.3, PHP introduced the namespace concept, so the above call will become
call_user_func(__NAMESPACE__.'::Demo::'.$action);
Seeing the code above, we can guess that the static method of the class is not a function with a namespace prefix.
Lambda and Closure in PHP
Before PHP 5.3, the syntax for implementing Lambda in PHP is very awkward. the code in the function should be passed as a string to the create_function method for construction.
$ Lambda = create_function ('$ A', 'Return addslashes (trim ($ a);'); // equivalent to constructing such a function: lambda1 ($) {return addslashes (trim ($ ));}
This kind of Lambda support is really amazing, but it reduces the efficiency.
Writing code to a string is prone to errors. This lambda creation method is only applicable to very short function expressions. let's look at what is saved in the above $ lambda variable.
Var_dump ($ lambda); // it is still a string type and named "lambda _" with a number // followed by a number as the global counter of the PHP System. This ensures that the operation will not be repeated.
In fact, the global function created with create_function is still a global function, but the name of this global function will not be guessed.
Maybe we will try to create a function named like this:
Function lambda_1 () {retunr 'lambda !!! ';}$ Lambda = create_function ('', 'Return 123;'); // if your PHP is run for the first time after the system is started, then the string in $ lambda looks the same as that in lambda_1 // but there is still no error in executing the code call echo $ lambda (); // 123 is returned; echo lambda_1 (); // return 'lambda !!! '
Actually, the name of the function generated by create_function is somewhat special. it is a NULL character plus "lambda _" and a digital identifier, the NULL character cannot be used when the function is declared. Therefore, the above code does not conflict. you can test it using the following code.
$ Lambda = create_function ('', 'Return 123; '); preg_match (' | \ d + | ', $ lambda, $ matches ); // match the lambda numeric ID // call some function expressions call_user_func ("\ x00lambda _ {$ matches [0]}") through the lambda numeric number; // add a NULL character before the string // always output 123
Using create_function is not only difficult to write, but the create_function method can only create general temporary functions.
Closure is not implemented (although it can be changed if only some scalar values are read, as shown below)
Function outer () {$ a = 123; return create_function ('$ a = '. $ a, 'return $ a; ') ;}$ inner = outer (); echo $ inner (); // PHP has a bad master who does not regard function calling as an expression. This type of code may have errors // outer (); or getRow () [0];
In PHP 5.3, PHP began to support true closures, and lambda was better suited to JavaScript.
#! /Usr/bin/php-5.3.0/php $ data = range (); // lambda syntax closer to JavaScript $ newData = array_map (function ($ v) {$ a = range (0, $ v); return array_sum ($ a) ;}, $ data); function outer () {$ a = 123; // The syntax is unfamiliar. the closure variables to be accessed in lambda are listed in the use list return function () use ($) {// closure echo $ a ;}}$ inner = outer (); // It's just uncomfortable that outer () cannot be written like this ()(); $ inner (); print_r ($ newData); // PHP also provides map, reduce, the walk method is used for functional programming. // The following code is used to trim array_walk ('trim', $ _ REQUEST) for each value in $ _ REQUEST );
For variable reference in PHP closures, the following code is somewhat different from the imagination.
function outer() { $a=0; return function () use($a) { return $a++; }; } $inner=outer(); echo $inner();//outputs 0 echo $inner();//outputs 0 echo $inner();//outputs 0
The closure in PHP only copies the values of the original variables. that is to say, the variables listed in use are partial variables in the closure function at runtime, it is not a variable outside the function.
Function outer () {$ a = 0; return function () use ($ a) {// basically has the following steps: lambda1 ::$ a = outer :: $ a return $ a ++ ;};}
If you want to reach the desired state, you only need to add a reference-based pass-through ID before the variable.
function outer() { $a=0; return function () use(&$a) { return $a++; }; } $inner=outer(); echo $inner();//0 echo $inner();//1 echo $inner();//2 echo $inner();//3
Bytes. PHP does not have the "function" type. that is to say, the function cannot directly use variables...