Re: Closure/lambda semantic comparaison
| From: | Etienne Kneuss | Date: | Mon, 01 Mar 2010 13:30:02 +0000 |
| Subject: | Re: Closure/lambda semantic comparaison | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-47071@lists.php.net to get a copy of this message | ||
Hello,
On Mon, Mar 1, 2010 at 1:33 PM, mathieu.suen <mathieu.suen@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