Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:43684 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 70810 invoked from network); 13 Apr 2009 21:03:15 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 13 Apr 2009 21:03:15 -0000 Authentication-Results: pb1.pair.com smtp.mail=stas@zend.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=stas@zend.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 63.205.162.116 as permitted sender) X-PHP-List-Original-Sender: stas@zend.com X-Host-Fingerprint: 63.205.162.116 us-gw1.zend.com Windows 2000 SP4, XP SP1 Received: from [63.205.162.116] ([63.205.162.116:58894] helo=us-gw1.zend.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 43/1D-22673-298A3E94 for ; Mon, 13 Apr 2009 17:03:15 -0400 Received: from [192.168.16.112] ([192.168.16.112]) by us-gw1.zend.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 13 Apr 2009 14:02:57 -0700 Message-ID: <49E3A890.2060009@zend.com> Date: Mon, 13 Apr 2009 14:03:12 -0700 Organization: Zend Technologies User-Agent: Thunderbird 2.0.0.21 (Windows/20090302) MIME-Version: 1.0 To: Peter Danenberg CC: internals@lists.php.net References: <20090412025100.GA5493@klutometis.wikitex.org> In-Reply-To: <20090412025100.GA5493@klutometis.wikitex.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 13 Apr 2009 21:02:57.0049 (UTC) FILETIME=[386DD090:01C9BC7B] Subject: Re: [PHP-DEV] Closures and __FUNCTION__ From: stas@zend.com (Stanislav Malyshev) Hi! > The original anonymous functions patch[1] contained support for > __FUNCTION__ as a recursion mechanism in closures, such that I should > be able to do something like this: > > $factorial = function($n) { > if ($n == 1) > return 1; > else > return $n * call_user_func(__FUNCTION__, $n - 1); > }; > > print $factorial(3); // => 6 You can also do it the hard way (that's how some languages not having luxury of being PHP do it ;), using something called Y-Combinator (http://en.wikipedia.org/wiki/Y_combinator), which allows you to unroll recursive function into non-recursive one. This looks like this: function Y($F) { $func = function ($f) { return $f($f); }; return $func(function ($f) use($F) { return $F(function ($x) use($f) { $ff = $f($f); return $ff($x); }); }); } This is the generic combinator function. Now your factorial function would look like: $factorial = Y(function($fact) { return function($n) use($fact) { return ($n == 0)?1:$n*$fact($n-1); }; }); And then you can do just this: var_dump($factorial(3)); Look, ma, no recursion! :) If it looks confusing, then you're right - it is :) It may be not what you would want to do in your code (or maybe you do), but this is yet another thing now possible with PHP. On the other hand, we may want to add some way to refer to the closure currently being run. We should have this information, so it should not be too hard to do. -- Stanislav Malyshev, Zend Software Architect stas@zend.com http://www.zend.com/ (408)253-8829 MSN: stas@zend.com