Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:88424 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 125 invoked from network); 22 Sep 2015 22:05:01 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 22 Sep 2015 22:05:01 -0000 Authentication-Results: pb1.pair.com smtp.mail=dmitry@zend.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=dmitry@zend.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 209.85.213.47 as permitted sender) X-PHP-List-Original-Sender: dmitry@zend.com X-Host-Fingerprint: 209.85.213.47 mail-vk0-f47.google.com Received: from [209.85.213.47] ([209.85.213.47:35781] helo=mail-vk0-f47.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id B7/61-22010-B80D1065 for ; Tue, 22 Sep 2015 18:05:00 -0400 Received: by vkao3 with SMTP id o3so16121836vka.2 for ; Tue, 22 Sep 2015 15:04:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=VGni2wrRy5koAJJEk2jnEe/DVQGmh0rYb06mVYioOdc=; b=XFsummIEajaZuhAwrPKQpVupjvT71M/xaHZwQ49Fj6pbgAsuni6QwRm5BRXqWBjw3q n6/WSp5/nvPaOVW88qVe1n8YI/SxqS+ZZhWExJT+4hBZtPS5E5LvwXOBLZPYDpynFbF5 1RBowPePa+sVLjQ9XpQexpYn8yck4ReGNEYMDM9zGUdvashSZutmKvDGliuHnXJztafE Gh9o8v9PYVawEBvdmTP4xtqMXNcaPPzcGMm6izEimpOiYbCKNNnEsCX+PNqHMMYlHjND yUjlyBNcgtqo9XhLksQCTO+NXXZcquUgkxOzkUQyelko/Hb4x5fJKgRaHNiHsgZ6IFdC /87w== X-Gm-Message-State: ALoCoQllNLHuzeMRFltEKe3+iItgHLpF+nbh5o8pEsY/ClC2ToF+2CNy50GpWK+e0WzAkMLmueGlEvR0sxrTudhaYrupTglaBcOS86aOGRErOKBkKuUTsyHCqrh48NFQGTt9eQymerj59+DDXYeia+UgYEn04DjuV78z8FgQEOKrO6z/7ScniaI= MIME-Version: 1.0 X-Received: by 10.31.108.91 with SMTP id h88mr17722090vkc.57.1442959496588; Tue, 22 Sep 2015 15:04:56 -0700 (PDT) Received: by 10.103.24.5 with HTTP; Tue, 22 Sep 2015 15:04:56 -0700 (PDT) In-Reply-To: References: Date: Wed, 23 Sep 2015 01:04:56 +0300 Message-ID: To: Anthony Ferrara Cc: Bob Weinand , Joe Watkins , PHP internals Content-Type: multipart/alternative; boundary=001a11478f44384bc505205d30a2 Subject: Re: [PHP-DEV] [RFC] [VOTE] Short Closures From: dmitry@zend.com (Dmitry Stogov) --001a11478f44384bc505205d30a2 Content-Type: text/plain; charset=UTF-8 On Wed, Sep 23, 2015 at 12:00 AM, Anthony Ferrara wrote: > Dmitry, > > On Tue, Sep 22, 2015 at 3:19 PM, Dmitry Stogov wrote: > > > > > > On Tue, Sep 22, 2015 at 9:20 PM, Anthony Ferrara > > wrote: > >> > >> Dmitry, > >> > >> On Tue, Sep 22, 2015 at 2:05 PM, Dmitry Stogov wrote: > >> > On Tue, Sep 22, 2015 at 7:01 PM, Bob Weinand > >> > wrote: > >> > > >> >> > >> >> > Am 22.09.2015 um 17:36 schrieb Dmitry Stogov : > >> >> > > >> >> > On Tue, Sep 22, 2015 at 4:54 PM, Joe Watkins < > pthreads@pthreads.org> > >> >> wrote: > >> >> > > >> >> >> I'd really like to understand what you're trying to say there > >> >> >> Dmitry, > >> >> but > >> >> >> I don't get it. > >> >> >> > >> >> >> What is your example function trying to show ? > >> >> >> > >> >> >> As it mentions in the RFC, vars in short closure are by-value, so > I > >> >> can't > >> >> >> see what side effects you might be thinking of ? > >> >> >> > >> >> > > >> >> > It's clear to me that foo() will return NULL, but how many warnings > >> >> > about > >> >> > unused variable $y will we get? > >> >> > > >> >> > Thanks. Dmitry. > >> >> > > >> >> > > >> >> >> > >> >> >> Cheers > >> >> >> Joe > >> >> >> > >> >> >> On Tue, Sep 22, 2015 at 9:25 AM, Dmitry Stogov > >> >> >> wrote: > >> >> >> > >> >> >>> I'm against the magic - "automatically use () all of the > (compiled) > >> >> >>> variables". > >> >> >>> I'm also against compound short closures with curly brackets. > >> >> >>> in my opinion they opens too many ambiguous questions. > >> >> >>> > >> >> >>> function foo() { > >> >> >>> (($x) ~> {$y = 3; return $y + $x;})(5); > >> >> >>> return $y; > >> >> >>> } > >> >> >>> > >> >> >>> also think about nested closures and use of variables from not > >> >> >>> direct > >> >> >>> enclosure. > >> >> >>> > >> >> >>> I'm not sure if we need all "functional programming" features in > >> >> >>> PHP, > >> >> but > >> >> >>> if we introduce them, lets do it consistently with the existing > >> >> language. > >> >> >>> I think, this proposal can't be approved without support for type > >> >> hinting. > >> >> >>> > >> >> >>> Thanks. Dmitry. > >> >> >>> > >> >> >>> On Tue, Sep 22, 2015 at 4:59 AM, Bob Weinand < > bobwei9@hotmail.com> > >> >> wrote: > >> >> >>> > >> >> >>>> Hey, > >> >> >>>> > >> >> >>>> Thanks for all your feedback in the discussion thread! > >> >> >>>> > >> >> >>>> So, before I start the vote, just two quick notes: > >> >> >>>> I've added two notes about the statement syntax and the single > >> >> variable > >> >> >>>> use. > >> >> >>>> Though a few people complained, I'm not switching to the ==> > >> >> >>>> operator, > >> >> >>> as > >> >> >>>> I noticed many people expected typehints to work (they don't due > >> >> >>>> to > >> >> >>> parser > >> >> >>>> limitations) when they compared to Hack's short Closures. It > also > >> >> >>> allows us > >> >> >>>> to differ syntax-wise [e.g. for typehints] from Hack without > >> >> >>>> causing > >> >> any > >> >> >>>> confusion later. Which should be the smartest choice: Avoid > >> >> >>>> conflicts. > >> >> >>> (If > >> >> >>>> anyone strongly feels against that, he may vote no, but I would > >> >> >>>> like > >> >> to > >> >> >>> not > >> >> >>>> bikeshed that in this Vote thread, but leave it free for > eventual > >> >> actual > >> >> >>>> issues.) > >> >> >>>> > >> >> >>>> Now, the link to the RFC about Short Closures: > >> >> >>>> https://wiki.php.net/rfc/short_closures > >> >> >>>> or straight ahead to the vote: > >> >> >>>> https://wiki.php.net/rfc/short_closures#vote > >> >> >>>> > >> >> >>>> Thanks, > >> >> >>>> Bob > >> >> > >> >> > >> >> Notice: Undefined variable: y in php shell code on line 3 > >> >> > >> >> It just yields exactly one notice about the inexistent $y (as it > >> >> obviously > >> >> does not leak through the scope): by-value binding. > >> >> > >> >> I'm not sure what your issue here is? > >> >> > >> > > >> > The current PHP version emits two warning on similar constructs, and > >> > this > >> > is explainable because we explicitly "use" $y. > >> > > >> > $ sapi/cli/php -r 'function foo(){(function($x) use ($y){$y=3; return > >> > $y+$x;})(5);return $y;} var_dump(foo());' > >> > PHP Notice: Undefined variable: y in Command line code on line 1 > >> > > >> > PHP Notice: Undefined variable: y in Command line code on line 1 > >> > > >> > NULL > >> > > >> > >> There's an important distinction here. The explicit `use($y)` triggers > >> a notice because you said to use an undefined variable. > >> > >> function foo() { > >> (($x) ~> {$y = 3; return $y + $x;})(5); > >> return $y; > >> } > >> > >> In this case, there's no practical binding of `$y` at all. The `$y` in > >> the scope of the closure is never actually read from before it is > >> assigned to. Meaning the variable doesn't need to exist prior to that > >> assignment, meaning that it doesn't have to be bound (used), and as > >> such shouldn't throw a notice. > > > > > > This is not the way like PHP works and the proposed patch didn't change > > this. > > It produced warning on "implicit" use. > > Now Bob seems to fixed this by hiding the warning. > > > >> > >> > >> This becomes a ton easier if we ever move to an explicit CFG+SSA > >> compile step. Then, we can see which variables dominate the closure to > >> see what needs to be bound vs what doesn't. In this example, converted > >> to SSA, you'd see: > >> > >> function foo() { > >> $y1 = 12; > >> (($x1) ~> {$y2 = 3; return $y2 + $x1;})(5); > >> return $y1; > >> } > >> > >> Hence you can see that `$y2` is truly an independent variable, and > >> hence `$y1` never needs to be bound (and hence no notice). > >> > >> So your case of explicitly using `$y` isn't actually what's happening > >> with the closure (at least with respect to userland behavior). Hence > >> why the lack of notice exists. > >> > >> My $0.02 at least, > > > > > > This is interesting, and I also thought about this. > > But this is going to be different language with different rules. > > Also, this approach can't handle all possible cases in dynamic languages, > > where we can't say if variable is used or assigned first. > > > > function foo() { > > $y = 1; > > $f = ($x) ~> { > > for ($i = 0; $i < 2; $i++) { > > if ($x) { > > $y = 5; > > } else { > > echo $y > > } > > }; > > $f(0); > > $f(1); > > } > > > > Your approach won't be able to determine if $y in short closure is local > > variable or from function foo(). > > Anyway, this is not related to Bob's proposal. > > Yes it can. Because the usages of `$y` are not fully dominated by an > assignment, there is at least one path from `$y = 1` to `echo $y` that > exists (this is trivial to prove). Hence the binding would need to > happen (no matter if that path was chosen by the actual execution > path). > So if we have at least one path that assumes use before local assignment we will use variable from the upper context. This should work. What if upper function doesn't have such variable? should it be created or should we use local instead? What if the upper context is global and at compile-time we don't know if used variable exists or not? I think, we may collect all variables of lambda that may be used before initialized at compile-time. At runtime we may check if upper syntax context (or even contexts) define required vars and bind them. This probably may work for binding by value. Use by reference will still require explicit definition. I don't think we can implement this in PHP (big conceptual change). Variable-variables would need to be taken into account, but that would > be easy to solve by saying if we see a Var-Var usage, bind everything > unless we can prove the variable is dominated inside the lambda. > var-var, eval(), references and aliases make huge troubles for compile-time decisions :( > > And this is related to Bob's proposal in a way. Right now, he has to > bind every symbol that exists in the closure using a non-notice read > (if it exists in the parent, bind, otherwise don't notice). The point > I was making is that if we modify our compiler it can get even > smarter, reducing the cases where we over-bind (and thereby making it > more efficient). Considering that some people are concerned around the > performance implications of the binding, possible solutions to that > problem do exist and could be implemented. > In general, this is possible, but SSA construction is much more difficult than the proposed by Bob patch. Thanks. Dmitry. > > Anthony > --001a11478f44384bc505205d30a2--