Hello, On Mon, Mar 1, 2010 at 1:33 PM, mathieu.suen <mathieu.s...@easyflirt.com> wrote: > 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)) > (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); > } >
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;". > Thanks for your attention > > -- Mathieu Suen > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > -- Etienne Kneuss http://www.colder.ch -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php