Re: Closure/lambda semantic comparaison
| From: | mathieu.suen | Date: | Mon, 01 Mar 2010 14:14:52 +0000 |
| Subject: | Re: Closure/lambda semantic comparaison | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-47072@lists.php.net to get a copy of this message | ||
Etienne Kneuss wrote:
Hello, On Mon, Mar 1, 2010 at 1:33 PM, mathieu.suen <mathieu.suen@easyflirt.com> wrote:You call it import by copy. I would rather say a mix-up of concept between value and variable.Hi, I am proposing a comparison between PHP closure with lisp one. First thing to compare is how scope are capture: Suppose I want to create a function that add. The common idiom to do it in lisp is: (defun adder (x) #'(lambda (y) (+ x y))) Then if I want the add3 method you can do: (setf (symbol-function 'add3) (adder 3)) (add3 4) => 7 Now let reproduce that in php: $adder = function ($x) {return function ($y) use($x) {return $y + $x;};}; $add3 = $adder(3); echo $add3(4); => 7 Every thing is fine but let change the adder into a counter : In lisp you could do: (let ((sum 0))use($var) will import by copy, so you won't have the behavior you expect. If you want to keep a value in a function between calls, you can use "static $sum = 0;".(defun counter () (setf sum (1+ sum))))(counter) => 1 (counter) => 2 (counter) => 3 ... In other to have the same behavior in PHP you first need to transform the let into a lambda which make no difference in lisp: (funcall #'(lambda (sum) (defun counter () (setf sum (1+ sum)))) 0) Now we are ready to do it in PHP. $createCounter = function ($sum) { return function () use ($sum) {return ++$sum;};}; $counter = $createCounter(0); $counter(); => 1 $counter(); => 1 $counter(); => 1 ... So that's not the expected behavior. In oder to have the expected behavior you need to add & in front of $sum. But & is kind of evil since it mimics dynamic scoping: $array = array(1, 2, 3); foreach($array as $pos) { $adders[] = function ($x) use (&$pos) { return $pos+ $x;}; } foreach($adders as $addIt) { echo $addIt(5); }
-- Mathieu SuenThanks for your attention -- Mathieu Suen -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php