Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:47072 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 80017 invoked from network); 1 Mar 2010 14:15:00 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Mar 2010 14:15:00 -0000 Authentication-Results: pb1.pair.com header.from=mathieu.suen@easyflirt.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=mathieu.suen@easyflirt.com; spf=pass; 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:38384] helo=mail.easyflirt.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id CC/0A-16552-2EBCB8B4 for ; Mon, 01 Mar 2010 09:15:00 -0500 Received: from [192.168.0.51] (office.easyrencontre.com [78.155.152.6]) by mail.easyflirt.com (Postfix) with ESMTPSA id 99520636D60; Mon, 1 Mar 2010 15:14:55 +0100 (CET) Message-ID: <4B8BCBDC.8040909@easyflirt.com> Date: Mon, 01 Mar 2010 15:14:52 +0100 User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: Etienne Kneuss CC: internals@lists.php.net References: <4B8BB419.8050402@easyflirt.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Closure/lambda semantic comparaison From: mathieu.suen@easyflirt.com ("mathieu.suen") Etienne Kneuss wrote: > Hello, > > On Mon, Mar 1, 2010 at 1:33 PM, mathieu.suen 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;". > You call it import by copy. I would rather say a mix-up of concept between value and variable. > >> Thanks for your attention >> >> -- Mathieu Suen >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> >> >> -- Mathieu Suen