Home
About
Search
🌐
English Română
  • Closures, from Scheme to Javascript to PHP

    Citește postarea în română

    Apr 10, 2013 anonymous functions closures JavaScript PHP php5.3 php5.4 Scheme
    Share on:

    The notion of closure in PHP, even though it appeared in PHP 5.3, as I’ve said before on my blog, it was properly done only in 5.4.

    Wikipedia tells us:

    In computer science, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables) of that function.

    In PHP this isn’t a very popular concept or very well-known. It is often mistaken for Anonymous Functions. But in functional programming languages it is very popular, because they really need it!

    Scheme

    When Brendan Eich designed JavaScript, relied on the Scheme language and ended up doing an implementation of this language with a C syntax. The C syntax was and is a lot more popular, and back then (1995) the Java programming language was very “fashionable”.

    The Scheme syntax is similar to Lisp, in the sens that is using parenthesis abound expressions in order to execute them. The operators are defined as functions and just like them, there must be placed left of the parenthesis.

    Let’s take an Scheme closure example:

    1(define (make-counter)
    2  (let ((count (begin 
    3                 (display "run parent function and return 0") 
    4                 )))
    5    (lambda ()
    6      (set! count (+ count 1))
    7      (begin 
    8        (display "inside child function ") 
    9        count))))
    

    The function is setting a “count” variable, with the value 0 and displays “run parent function and return 0”, then returns another lambda function, that is incrementing the variable defined in the main function and then displays “inside child function”.

    I’m storing the resulting function in a variable in order to later run it multiple times:

    1> (define counter (make-counter))
    2run parent function and return 0
    3> (counter)
    4inside child function 1
    5> (counter)
    6inside child function 2
    

    In other words, each time I’m calling (make-counter), it will return a new function that has access to the environment at the time at which it was created. If it looks strange because of the syntax, I promise that it will fell a lot more natural in JavaScript.

    This concept is very interesting for encapsulation. The environment from the time when the parent function was been executed can be encapsulated, and later it can be used without worrying that it was changed by external causes.

    For the functional programming languages this is a very interesting concept. Yet when it comes to object orientated languages, the concept seems almost useless, because objects also have the purpose of encapsulation.

    JavaScript

    From the beginning JavaScript was a hybrid, a functional programming language, object orientated, with prototype based inheritance. And if this wasn’t enough, the syntax was taken from Java (C).

    JavaScript didn’t inherited a lot from Scheme, but it did inherit the closure concept.

    A reason why there was a need for closures in Scheme is that that if a function is not finding a variable in its environment, it will search for it in its container’s environment. Let’s take an example:

    1(define x 1)
    2(define (add-in-env y) (+ x y))
    

    If we call add-in-env with 2:

    1(add-in-env 2) -> 3
    

    It looks just as ambiguous as in JavaScript, but is not exactly like that. In Scheme to do mutation is not that easy, simple and transparent, so an subsequent operation of:

    1(define x 2)
    

    will result in an error.

    In JavaScript resulted a hybrid. Mutation is permitted, but the notion of searching a variable in the current environment remained:

    1var x = 1;
    2var add_in_env = function (y) {
    3   return x + y;
    4}
    5
    6add_in_env(2); // returns 3
    

    Up to this point is ok, but for:

    1x = 2;
    2add_in_env(2); // returns 4
    

    For this case, things can get out of hand very easy:

    But, in order to solve the issue, we can just define a variable in the environment that will finish execution (will close):

     1var make_counter = function () {
     2   console.log("run parent function and set counter to 0")
     3   var count = 0;
     4
     5   return function () {
     6       count = count + 1;
     7       console.log("inside child function");
     8       return count;
     9   }
    10}
    11
    12var counter = make_counter();
    13console.log(counter());
    14console.log(counter());
    15
    16var counter2 = make_counter();
    17console.log(counter2());
    18console.log(counter());
    19console.log(counter2());
    

    The output will be:

     1run parent function and set counter to 0
     2inside child function
     31
     4inside child function
     52
     6run parent function and set counter to 0
     7inside child function
     81
     9inside child function
    103
    11inside child function
    122
    

    Even though the main function finished executing, the environment inside it is kept as a closure for the function that was returned. Only when there aren’t any more references to the sub-function the memory allocated for the closure will also be deallocated.

    Even though JavaScript has objects, it doesn’t have private methods. An approach is to add a “_” (underscore) in front of the function name and consider it private. From my point is like asking the developers that will later use the code to consider this function private. Of course this is not very consistent.

    Let’s take an example:

    1var obj = {
    2   _secretFunction : function (key) { console.log(‘do secret ’ + key) },
    3   doStuff : function (key) { this._secretFunction(key) }
    4}
    5
    6obj.doStuff(‘stuff’); // do secret stuff
    

    It seems that there is a public method “doStuff” and a private one “_secretFunction”. Nevertheless you can not prevent a user from calling “_secretFunction” or even worse, to modify it:

    1obj._secretFunction = function (key) { console.log('new secret ' + key); }
    2
    3obj.doStuff('stuff'); // new secret stuff
    

    If we want to hide the function, and make this obvious for everybody, again, we can use closures:

     1var obj = (function () {
     2   var secretFunction =  function (key) { console.log(‘do secret ’ + key) }
     3
     4   return {
     5      doStuff : function (key) { 
     6         secretFunction(key) 
     7      }
     8   }
     9})();
    10
    11obj.doStuff(‘stuff’); // do secret stuff
    

    Because the parent function was not stored but rather immediately executed, basically the space in which secretFunction was defined has already finished its execution, encapsulating the logic. The object returned can call the function because it was defined in the same environment as the object.

    Looks complicated at first, but is really very easy when you understand the concept.

    And then it was… PHP

    PHP includes a lot of different options. It was originally developed as a Perl framework, later the engine was rewritten in C.

    PHP is a dynamic language that includes a lot of concepts, from objects, interfaces and anonymous functions, up to goto labels. The development direction for the language is not very clear, it rather offers the possibility for different approaches.

    In the weird PHP history, somewhere in version 4, syntax for Anonymous Functions was added, but only in PHP 5.3 a more “normal” version appeared.

    Also in version 5.3 the first closure version was introduced:

     1$scalar = 5;
     2
     3$closure = function () use ($scalar) {
     4     return 'Scalar: ' . $scalar . PHP_EOL;
     5};
     6
     7echo $closure(); // Scalar: 5
     8
     9$scalar = 7;
    10
    11echo $closure(); // Scalar: 5
    

    This version mostly worked, but you had to specify what you want to send to the closure.

    And there were other inconveniences:

     1<?php 
     2class Foo {         
     3   private function privateMethod() {                 
     4      return 'Inside private method';         
     5   }
     6
     7   public function bar() {                 
     8      $obj = $this;                 
     9      return function () use ($obj) {                         
    10         return $obj->privateMethod();
    11      };
    12   }
    13}
    14
    15$obj = new Foo();
    16$closure = $obj->bar();
    17echo $closure();
    18
    19Fatal error:  Call to private method Foo::privateMethod() from context '' in [...][...] on line 10
    

    Is not working because you can not send $this as a parameter to a closure, and if you try the above trick you still can’t access the private methods. Remember, this was happening in PHP 5.3.

    The idea to introduce a closure of this kind seems strange to me. But this is not the first time something “strange” is introduced in PHP, as I was saying before about the Anonymous Functions. Sometimes is looking like work in progress.

    I think everybody was expecting a more JavaScript like closures. I think that JavaScript had a big influence in making this concept so popular.

    In version PHP 5.4 things changed, we finally have a closure as we would expect:

     1class Foo {
     2   private function privateMethod() {
     3      return 'Inside private method';
     4   }
     5
     6   public function bar() {
     7      return function () {
     8         return $this->privateMethod();
     9      };
    10   }
    11}
    12
    13$obj = new Foo();
    14$closure = $obj->bar();
    15echo $closure(); // Inside private method
    

    And it works!

    You can even do:

    1unset($obj);
    2echo $closure();
    

    and it will work, because the object in which the closure was defined remains in memory until either the script finishes execution, or a call like this is made:

    1unset($closure);
    

    For more details on how closures work in PHP 5.4, check out this post.

  • PHP 5.4 – Closures the right way!

    Citește postarea în română

    Feb 11, 2012 anonymous functions closures PHP php5.3 php5.4
    Share on:

    The concept of closure was introduced in PHP 5.3, with the new “more traditional” syntax for anonymous functions.

    PHP 5.3

    In PHP 5.3, a closure will rely on the term “use”, which was passing the variables to the anonymous function, making it a closure.

    The problem is that the anonymous function will only be able to access the variables that have been passed with “use”. When it comes to objects, there are passed by reference by default, but scalar variables (int, string, etc.) are passed by value, as this is the default behavior in PHP 5+:

     1$scalar = 5;
     2
     3$closure = function () use ($scalar) {
     4     return 'Scalar: ' . $scalar . PHP_EOL;
     5};
     6
     7echo $closure(); // Scalar: 5
     8
     9$scalar = 7;
    10
    11echo $closure(); // Scalar: 5
    

    Another problem is that you cannot pass $this when the anonymous function is declared inside an object, so only the public method and properties can be accessed inside the closure.

    PHP 5.4

    In PHP 5.4 the keyword “use” is optional, and the entire environment where the function was created is available inside the function.

    The advantage is that when the anonymous function is created inside another function or method, the anonymous function has access to the environment where it was created, even after the execution of the environment is over. The objects from this environment will be unset, only after the last reference to the closure will be unset:

     1class testClass {
     2
     3        private $changeableVar = 1;
     4        private $bigVar;
     5
     6        public function __construct() {
     7                // Allocate a big variable so we can see the changes in memory
     8                $this->bigVar = str_repeat("BigWord", 5000);
     9        }
    10
    11        /**
    12         * A method that returns the closure
    13         */
    14        public function closure() {
    15
    16                return function () {
    17                        // Display the value of a private property of the object
    18                        echo 'Private property: ' . $this->changeableVar.PHP_EOL;
    19
    20                        // Change the value of a private property of the object
    21                        $this->changeableVar = 2;
    22                };
    23        }
    24
    25        /**
    26         * Method that displays a private property
    27         */
    28        public function showChangeableVar() {
    29                echo 'Private property in method: ' . $this->changeableVar.PHP_EOL;
    30        }
    31
    32}
    33
    34// Memory befor the objects is created
    35echo "Memory: " . memory_get_usage() . PHP_EOL; // Memory: 229896
    36
    37// Create object
    38$testObj = new testClass();
    39
    40// Create closure
    41$closure = $testObj->closure();
    42
    43// Execute closure
    44$closure(); // Private property: 1
    45
    46// Displaying the current value of the private property
    47$testObj->showChangeableVar(); // Private property in method: 2
    48
    49// Memory befor object will be unset
    50echo "Memory: ". memory_get_usage() . PHP_EOL; // Memory: 266240
    51
    52// Unset the object
    53unset($testObj);
    54
    55// Memory after the object was distroyed, there is no big difference in memory
    56echo "Memory: ". memory_get_usage() . PHP_EOL; // Memory: 266152
    57
    58// Run closure after the object in which it was created was unset
    59echo $closure(); // Private property: 2
    60
    61// Unset closure and with it the object environment
    62unset($closure);
    63
    64// Memotry after the las reference to the object (closure) is unset
    65echo "Memory: " . memory_get_usage() . PHP_EOL; // Memory: 230416
    

    Callable type hinting

    Another new feature introduced in PHP 5.4 regarding closures is the new “type hint”: “callable”. Actually callable is referring to any anonymous function, and even to a new way of calling a method of an object:

     1<?php
     2
     3// A function that uses type hinting
     4function typeHinting(callable $a) {
     5     echo $a() . PHP_EOL;
     6}
     7
     8// A closure
     9$closure = function () {
    10     return __FUNCTION__;
    11};
    12
    13// Call the type hinting function with the closure
    14typeHinting($closure); // {closure}
    15
    16class testClass {
    17     public function testMethod() {
    18          return __METHOD__;
    19     }
    20}
    21
    22// A mock object
    23$testObj = new testClass();
    24
    25// The new way of calling object methods
    26$objCallable = array($testObj, 'testMethod');
    27
    28// Call type hinting function with the new method calling way
    29typeHinting($objCallable); // testClass::testMethod
    

    I believe that only now we can really say that PHP supports closures, the right way!

  • Closures and lambda functions in PHP vs. JavaScript

    Citește postarea în română

    Apr 16, 2011 anonymous functions closures JavaScript lambda PHP php5.3
    Share on:

    JavaScript and PHP support both lambda functions and closures. But the terms are poorly understood in both programming languages ​​and are often confused with each other.

    Lambda functions

    Also called anonymous functions. They refer to functions that can be called without being bound to an identifier. One of their purposes is to be passed as arguments. The Lambda name was introduced by Alonzo Church, inventor of lambda calculus in 1936. In lambda calculus all functions are anonymous.

    JavaScript

    In JavaScript lambdas are part of the standard set and there are the preferred method of defining functions.

    For instance:

    1var add = function (a, b) {
    2     return a + b;
    3}
    4alert(add(1, 2)); // 3
    

    Lambda functions are used almost in any context when it comes to JavaScript, like:

    1window.onload = function (e) {
    2     alert('The page has loaded!');
    3}
    

    PHP

    In PHP, lambda functions were introduced in version 4.0.1 using create_function. In version 5.3+ a similar syntax to JavaScript was added, a much more readable and elegant way of defining a function.

    This means that in PHP there are two ways of creating a lambda function:

     1// PHP 4.0.1+
     2$add = create_function('$a, $b', 'return $a + $b;');
     3
     4// vs.
     5
     6// PHP 5.3+
     7$add = function ($a, $b) {
     8     return $a + $b;
     9};
    10
    11echo $a(1,2); // 3
    

    Lambda functions can be used as parameter for other functions, such as usort:

    1$array = array(4, 3, 5, 1, 2);
    2usort($array, function ($a, $b) {
    3     if ($a == $b) {
    4          return 0;
    5     }
    6     return ($a < $b) ? -1 : 1;
    7});
    

    Even more, PHP 5.3+ allows calling an object as a anonymous function:

    1class test {
    2     function __invoke($a) {
    3          echo $a;
    4     }
    5}
    6$a = new test();
    7$a('test'); // 'test'
    

    Closures

    The closure is really the misunderstood concept of the two. In general confusion appears because closures may involve lambda functions. A closure refers to the ability of a function/object to access the scope in which it was created even if the parent function has ended it’s execution and returned. In other words, the function/object returned by a closure is running in the scope in which it was defined.

    In JavaScript the notion of closure is part of the standard arsenal, because the language is not based on the traditional object model, but rather on prototypes and functions. But JavaScript has some traditional object model parts, like the fact that you can use “new” to construct an object based on a function that plays the role of a class. In PHP closures are more of an new way to approach problems, because PHP is part of the traditional object model family.

    JavaScript

    In JavaScript the notion of closure is widely used, it’s so popular because JavaScript is not a traditional object orientated language, but rather a functional one, based on prototype inheritance.

    JavaScript doesn’t have Public, Private and Protected, but rather only Public and Private and objects an inherit from each other, without using classes.

    Another issue is the scope, because the global scope is used by default. This issues can be fixed in an elegant fashion using closures:

     1var closure = function () {
     2     var sum = 0;
     3     return {
     4          add: function (nr) {
     5               sum += nr;
     6          },
     7          getSum: function () {
     8               return sum;
     9          }
    10     }
    11}();
    12
    13closure.add(1);
    14closure.add(2);
    15console.log(closure.getSum());
    

    In the example above, sum is a private property and in theory can only be accessed and modified by the closure function. The interesting part is that the parentheses from the end of the function definition, signify that this function will be immediately  executed and therefore will return the result which is an object. At this point the original function will only exist for serving the return object, encapsulating therefor the private variable.

    Although the function has finished execution, through this closure the returned object can still access the variables defined in the function scope, because that was the environment in which it was created.

    This becomes even more interesting when a function returns another function:

     1var counter = function () {
     2    var counter = 0;
     3    console.log('in closure');
     4    return function () {
     5        console.log('in the anonymous function');
     6        return ++counter;
     7    };
     8};
     9var counter1 = counter();
    10
    11console.log(counter1()); // 1
    12
    13var counter2 = counter();
    14console.log(counter2()); // 1
    15console.log(counter1()); // 2
    

    The output will be:

    1in closure
    2in the anonymous function
    31
    4in closure
    5in the anonymous function
    61
    7in the anonymous function
    82
    

    What actually happens is that the first function is executed and returns an anonymous function that can still access the environment in which it was created. In my opinion this is where the confusion between closures and lambda functions comes from, because a function returns another function.

    The difference between examples is that in the first one the closure function executes immediately, and in the second example when counter is executed it’s returning a result that is actually a function definition, which in turn can be executed. Of course the second example can be modified to act just like in the first example using parenthesis.

    PHP

    As I said above, the notion of closure in PHP is not as important as in JavaScript.

    Considering that lambda functions are available in the language since version 4, closures only appeared with PHP 5.3+.

    Because of the block scope nature of PHP, there is a better encapsulation but there is a lot less flexibility compared to JavaScript. Basically in PHP you must specify using the use instruction what will the anonymous function be able to access from the closure scope.

     1function closure () {
     2     $c = 0;
     3     return function ($a) use (&$c) {
     4          $c += $a;
     5          echo $a . ', ' . $c . PHP_EOL;
     6     };
     7}
     8
     9$closure = closure();
    10
    11$closure(1);
    12$closure(2);
    

    Unlike JavaScript, in PHP closures can not return objects, or rather the object can not be bound to the scope in which it was created, unless you send the variables as a reference to the constructor, in which case is not very elegant and I can’t imagine a scenario that would absolutely need closure for this.

    Like in the JavaScript examples, instead of parentheses “()” at the end of the function, in PHP to run a function immediately after defining it call_user_func() or call_user_func_array() can be used:

     1$closure = call_user_func(function () {
     2    $c = 0;
     3    return function ($a) use (&$c) {
     4        $c += $a;
     5        echo $a . ', ' . $c . PHP_EOL;
     6
     7    };
     8});
     9
    10$closure(1);
    11$closure(2);
    

Claudiu Perșoiu

Programming, technology and more
Read More

Recent Posts

  • Adding a slider to Tasmota using BerryScript
  • The future proof project
  • Docker inside wsl2
  • Moving away from Wordpress
  • Custom path for Composer cache
  • Magento2 and the ugly truth
  • A bit of PHP, Go, FFI and holiday spirit
  • How to make use of the Xiaomi Air Conditioning Companion in Home Assistant in only 20 easy steps!

PHP 49 MISCELLANEOUS 46 JAVASCRIPT 14 MAGENTO 7 MYSQL 7 BROWSERS 6 DESIGN PATTERNS 5 HOME AUTOMATION 2 LINUX-UNIX 2 WEB STUFF 2 GO 1

PHP 35 JAVASCRIPT 15 PHP5.3 11 MAGENTO 7 PHP6 7 MYSQL 6 PHP5.4 6 ZCE 6 CERTIFICARE 5 CERTIFICATION 5 CLOSURES 4 DESIGN PATTERNS 4 HACK 4 ANDROID 3
All tags
3D1 ADOBE AIR2 ANDROID3 ANGULAR1 ANONYMOUS FUNCTIONS3 BERRYSCRIPT1 BOOK1 BROWSER2 CARTE1 CERTIFICARE5 CERTIFICATION5 CERTIFIED1 CERTIFIED DEVELOPER1 CHALLENGE1 CHM1 CLASS1 CLI2 CLOSURES4 CODE QUALITY1 CODEIGNITER3 COFFEESCRIPT1 COLLECTIONS1 COMPOSER1 CSS1 DEBUG1 DESIGN PATTERNS4 DEVELOPER1 DEVELOPMENT TIME1 DOCKER2 DOCKER-COMPOSE1 DOUGLAS CROCKFORD2 ELEPHPANT2 FACEBOOK2 FFI1 FINALLY1 FIREFOX3 GAMES1 GENERATOR1 GO1 GOOGLE1 GOOGLE CHROME1 GOOGLE MAPS1 HACK4 HOMEASSISTANT2 HTML2 HTML HELP WORKSHOP1 HTML51 HUG1 HUGO1 INFORMATION_SCHEMA1 INI1 INTERNET EXPLORER3 IPV41 IPV61 ITERATOR2 JAVASCRIPT15 JQUERY1 LAMBDA1 LINUX1 MAGENTO7 MAGENTO22 MAP1 MINESWEEPER1 MOTIVATION1 MYSQL6 NGINX1 NODE.JS2 NOSQL1 OBSERVER3 OBSERVER PATTERN1 OOP1 OPERA1 OPTIMIZATION1 ORACLE1 PAGESPEED1 PAIR1 PARSE_INI_FILE1 PHONEGAP2 PHP35 PHP ELEPHANT2 PHP FOR ANDROID1 PHP-GTK1 PHP42 PHP53 PHP5.311 PHP5.46 PHP5.53 PHP5.61 PHP67 PHP7.41 PROGRAMMING1 REVIEW1 ROMANIAN STEMMER2 SAFARY1 SCALAR TYPE HINTING1 SCHEME1 SET1 SHOPPING CART PRICE RULE1 SINGLETON1 SOAP1 SPL2 SQLITE1 SSH1 STACK TRACE1 STDERR1 STDIN1 STDOUT1 SUN1 SYMFONY2 TASMOTA1 TEST TO SPEECH1 TITANIUM2 TRAITS1 TTS1 UBUNTU1 UNICODE2 UTF-82 VECTOR1 WEBKIT1 WINBINDER1 WINDOWS2 WORDPRESS1 WSL21 YAHOO3 YAHOO MAPS1 YAHOO OPEN HACK1 YSLOW1 YUI1 ZCE6 ZCE5.31 ZEND3 ZEND FRAMEWORK3
[A~Z][0~9]

Copyright © 2008 - 2024 CLAUDIU PERȘOIU'S BLOG. All Rights Reserved