Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:76417 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 59189 invoked from network); 10 Aug 2014 21:01:41 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 10 Aug 2014 21:01:41 -0000 Authentication-Results: pb1.pair.com smtp.mail=rowan.collins@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=rowan.collins@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.41 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 74.125.82.41 mail-wg0-f41.google.com Received: from [74.125.82.41] ([74.125.82.41:49036] helo=mail-wg0-f41.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 7D/00-56799-3BDD7E35 for ; Sun, 10 Aug 2014 17:01:41 -0400 Received: by mail-wg0-f41.google.com with SMTP id z12so7720465wgg.0 for ; Sun, 10 Aug 2014 14:02:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=user-agent:in-reply-to:references:mime-version :content-transfer-encoding:content-type:subject:from:date:to:cc :message-id; bh=mGqAGwml0MK1Vw+CCP0wr5l3Tj8b83dAbp+Cjdo/4BU=; b=ZjWevZY5GLGolqYF6QKJy7TbG0LGZu8IJIZpnVnT8p/6+g7zVATjs4fSizYku0Hx0o reBpbiWennZs+gK7nwN/Dgg6JoBdpt1Ymw5bMlEanmXY1FW/+GybgFIMoDOvV1oeRyOa 9B5KP/GP1iSzfhUrfa0JLSLUIJi/aQHvk8k2mRCou4Ap4h7/mRmNY2z1fSnVlClKvAXm 9Q9/PGVv8gkSnZixcZ8mEDOgD1Kd0erSfVwaRxI5Wh+OPPKRCDMMbJmYdenYYwj6PwB/ O98WXTllLDNNqg6J0xha6TF4EVbBx50CvVm8ZQY42tYk9/+I8Rm8b4WKAUIr7nJ1EuEO oXPw== X-Received: by 10.180.86.202 with SMTP id r10mr16244072wiz.6.1407704535759; Sun, 10 Aug 2014 14:02:15 -0700 (PDT) Received: from [192.168.0.6] (cpc19-brig17-2-0-cust25.3-3.cable.virginm.net. [81.101.201.26]) by mx.google.com with ESMTPSA id ev18sm7213927wid.1.2014.08.10.14.02.14 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 10 Aug 2014 14:02:14 -0700 (PDT) User-Agent: K-9 Mail for Android In-Reply-To: References: <53DF2BED.10103@sugarcrm.com> <06F3EF08-21B1-49AD-9D9D-5043C69AC1D8@ajf.me> <53DFE1FC.5040206@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Date: Sun, 10 Aug 2014 22:00:10 +0100 To: Andrea Faulds CC: "internals@lists.php.net" Message-ID: <4c89fa2a-a4da-46a9-9872-6d2e5346fed1@email.android.com> Subject: Re: [PHP-DEV] [RFC] Closure::call and Function Referencing as Closures From: rowan.collins@gmail.com (Rowan Collins) On 10 August 2014 19:20:09 GMT+01:00, Andrea Faulds wrote: >Hi! > >Sorry for the slow response, I’ve been on holiday. > >On 8 Aug 2014, at 01:32, Josh Watzman wrote: > >> The RFC goes a long way to fixing this, but one important place it >misses is with function references to private and protected methods. >The crux of the issue is that allowing an unbound closure to escape can >lead to very unexpected and unwanted results, as opposed to forcing the >closure to be bound to a particular variable. Consider: >> >> > class C { >> private function priv() { /* ... */ } >> public function pub() { >> // ... do stuff ... >> // Return a closure for the caller to call priv at a later date: >> return &self::priv; >> } >> } >> >> While this example is somewhat contrived, I've certainly wanted to do >something similar before. The intent of this code is for the closure >returned by "pub" to only ever be called on what was $this inside "pub" >-- but not only can you change that with bind() on the closure, "pub" >itself cannot even pre-bind it to the intended $this. Or maybe it >technically could by calling bind() on the result of &self::priv before >returning it, but that's very cumbersome for what is the common case >for what you want to do with "function pointer" to a non-static method. > >Unfortunately, yes, such closures are not pre-bound. However invoking >it when it’s unbound will produce the same error as calling any method >statically (E_STRICT or E_ERROR), so the issue can be noticed and fixed >easily. It’s possible to bind with Closure::bind(&Foo::bar, ‘Foo’); or >something like that. I could make it pre-bind, but I’m unwilling to as >:: never binds when calling, so it shouldn’t when referencing for >consistency. > You're rather pre-supposing the proposed syntax there, and letting it lead the semantics rather than vice versa. The point is it would be useful to allow creation of a pre-bound closure based on an existing method, so it would be good if the syntax allowed that possibility. Getting a static reference to a non-static method and then binding it feels a bit like JS, which has a completely different notion of what a method is. And it's noteworthy that pre-bound methods are one of the things being added in ECMAScript.next >Using the ‘Closure’ class is unfortunate, but I don’t really want to >make unnecessary new Function/Method/etc. classes given they’d all >share the same implementation anyway. I'm not so sure they'd be identical - a static method or plain function would presumably error if you tried to bind it, for instance. For whatever reason, there's a tendency for internal classes to take on multiple responsibilities which a userland framework would separate out - SimpleXML is the extreme example. If we were designing a fully OO language with first-class functions (which, clearly, we're not), a hierarchy of classes to represent different "states" of these immutable objects would be the obvious choice. The alternative (which SimpleXML is also missing, incidentally) is to have one class, but include methods for interrogating its type - e.g. isBound(), isBindable(), etc -- Rowan Collins [IMSoP]