Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:47070 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 66885 invoked from network); 1 Mar 2010 12:33:34 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Mar 2010 12:33:34 -0000 Authentication-Results: pb1.pair.com smtp.mail=mathieu.suen@easyflirt.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=mathieu.suen@easyflirt.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain easyflirt.com designates 91.199.255.56 as permitted sender) X-PHP-List-Original-Sender: mathieu.suen@easyflirt.com X-Host-Fingerprint: 91.199.255.56 python-06.easyrencontre.com Linux 2.6 Received: from [91.199.255.56] ([91.199.255.56:39110] helo=mail.easyflirt.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 5F/E7-16552-C14BB8B4 for ; Mon, 01 Mar 2010 07:33:33 -0500 Received: from [192.168.0.51] (office.easyrencontre.com [78.155.152.6]) by mail.easyflirt.com (Postfix) with ESMTPSA id 772876374D0 for ; Mon, 1 Mar 2010 13:33:29 +0100 (CET) Message-ID: <4B8BB419.8050402@easyflirt.com> Date: Mon, 01 Mar 2010 13:33:29 +0100 User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: internals@lists.php.net Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Closure/lambda semantic comparaison From: mathieu.suen@easyflirt.com ("mathieu.suen") 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); } Thanks for your attention -- Mathieu Suen