RFC proposal

php.internals

Bartłomiej Krukowski

9 years ago
Hello, I've created an account just now on wiki.php.net. My username: *bkrukowski*. I would like to create RFC about references in PHP. Could you please give me an access? Best regards

Dan Ackroyd

9 years ago
On 2 June 2017 at 12:14, Bartłomiej Krukowski <krukowski.bartlomiej@gmail.com> wrote:
> Hello, > > I've created an account just now on wiki.php.net. My username: *bkrukowski*. > I would like to create RFC about references in PHP. Could you please give > me an access? >
From the RFC howto https://wiki.php.net/rfc/howto: "Email internals@lists.php.net to measure reaction to your intended proposal. State who would implement the feature, or whether the proposal is only a “concept”. Proceed with an RFC if feedback is not negative or if a detailed RFC will clarify the proposal. " Can you give a rough outline of the proposal ? cheers Dan

Bartłomiej Krukowski

9 years ago
Hello, PHP allows for using implicit references in arguments of function. In most common case we have to mark that variable is an reference in head of function, in other case we will receive fatal error (@see example - http://ideone.com/7zkgQQ <http://ideone.com/7zkgQQ>). There is an option to use variable as implicit reference (@see example - http://ideone.com/T6oF7C <http://ideone.com/T6oF7C>), I think it should not be possible. Only explicit references should be allowed (except objects). Best regards 2017-06-02 14:19 GMT+02:00 Dan Ackroyd <danack@basereality.com>:

Rowan Collins

9 years ago
On 2 June 2017 14:21:38 BST, "Bartłomiej Krukowski" <krukowski.bartlomiej@gmail.com> wrote:
> There is an >option to >use variable as implicit reference (@see example - >http://ideone.com/T6oF7C ><http://ideone.com/T6oF7C>), I think it should not be possible. Only >explicit references should be allowed (except objects).
So in summary: a function given an array (or object) containing items assigned by reference can unknowingly "leak" its internal processing of that array. It's certainly an interesting case, but what is the alternative behaviour you would propose? Just banning all assignment to array items by reference would stop this, but also remove a potentially useful feature. Detecting or defeating this situation at the time a function is called might prove expensive in terms of processing and memory (e.g. unnecessarily cloning values), and the result would be a compatibility break for anyone using this, so it would require careful consideration. [Note: the convention on this list is to reply below quoted text, not above, when replying.] Regards,
-- Rowan Collins [IMSoP]

Johannes Schlueter

9 years ago
On Fr, 2017-06-02 at 15:21 +0200, Bartłomiej Krukowski wrote:
> Hello, > > PHP allows for using implicit references in arguments of function. In > most common case we have to mark that variable is an reference in > head of function, in other case we will receive fatal error (@see > example - http://ideone.com/7zkgQQ <http://ideone.com/7zkgQQ>). There > is an option to use variable as implicit reference (@see example - ht > tp://ideone.com/T6oF7C <http://ideone.com/T6oF7C>), I think it should > not be possible. Only explicit references should be allowed (except > objects).
The argument to the function in the second value is an array which is passed by value. A copy of the array keeps the references as references. This is consistent. Unless we have typed arrays or anything like that the function call shouldn't care about the content. Aside from that references are a legacy construct and shouldn't be used anymore. Using objects or relying on copy-on-write usually leads to clearer code, reduced memory and faster execution. (in the past there had been a few exceptions where arrays of references were good for some graphs/trees with recent improvements to objects this is less the case) johannes http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html http://schlueters.de/blog/archives/141-References-and-foreach.html http://schlueters.de/blog/archives/180-References-Still-bad-in-PHP-7.ht ml http://schlueters.de/blog/archives/181-More-on-references.html

Michael Morris

9 years ago
What about foreach by reference, which is honestly the only time I use referencing anymore... foreach ($array as $key => &$value) { $value = someOp($value); } Is this also bad? On Fri, Jun 2, 2017 at 10:56 AM, Johannes Schlüter <johannes@schlueters.de> wrote:

Levi Morrison

9 years ago
On Fri, Jun 2, 2017 at 11:12 AM, Michael Morris <tendoaki@gmail.com> wrote:
> What about foreach by reference, which is honestly the only time I use > referencing anymore... > > foreach ($array as $key => &$value) { > $value = someOp($value); > } > > Is this also bad?
I'm not going to say "bad" but I would not personally write it that way. If the memory cost is too high to duplicate then I'd use a generator that maps the value; I have this function in all my projects because it's fairly common anyway: function (callable $fn, iterable $input) { foreach ($input as $key => $value) { yield $iey => $fn($value); } }

Rowan Collins

9 years ago
On 2 June 2017 18:21:34 BST, Levi Morrison <levim@php.net> wrote:
>On Fri, Jun 2, 2017 at 11:12 AM, Michael Morris <tendoaki@gmail.com> >wrote: >> What about foreach by reference, which is honestly the only time I >use >> referencing anymore... >> >> foreach ($array as $key => &$value) { >> $value = someOp($value); >> } >> >> Is this also bad? > >I'm not going to say "bad" but I would not personally write it that >way. If the memory cost is too high to duplicate then ...
The times I've used foreach-by-reference have absolutely nothing to do with memory cost. Mostly, they're situations where explicitly writing back into the original array would be tediously long-winded, like this: $some_array[$some_outer_key][$loop_key]['foo'] = some_func($loop_value['foo']); $some_array[$some_outer_key][$loop_key]['bar'] = some_other_func($loop_value['bar'], true); Granted, there are probably major refactorings that would be in some way better, but changing $loop_value to a reference gives the much more readable: $loop_value['foo'] = some_func($loop_value['foo']); $loop_value['bar'] = some_other_func($loop_value['bar'], true); References are fiddly, but they do have their uses. Short of eliminating mutability, per functional programming, I think they'll always have their place, in some form. Regards,
-- Rowan Collins [IMSoP]

Michael Morris

9 years ago
On Fri, Jun 2, 2017 at 1:36 PM, Rowan Collins <rowan.collins@gmail.com> wrote:
> On 2 June 2017 18:21:34 BST, Levi Morrison <levim@php.net> wrote: > >On Fri, Jun 2, 2017 at 11:12 AM, Michael Morris <tendoaki@gmail.com> > >wrote: > >> What about foreach by reference, which is honestly the only time I > >use > >> referencing anymore... > >> > >> foreach ($array as $key => &$value) { > >> $value = someOp($value); > >> } > >> > >> Is this also bad? > > > >I'm not going to say "bad" but I would not personally write it that > >way. If the memory cost is too high to duplicate then ... > > The times I've used foreach-by-reference have absolutely nothing to do > with memory cost. Mostly, they're situations where explicitly writing back > into the original array would be tediously long-winded, like this: > > $some_array[$some_outer_key][$loop_key]['foo'] = > some_func($loop_value['foo']); > $some_array[$some_outer_key][$loop_key]['bar'] = > some_other_func($loop_value['bar'], true); > > Granted, there are probably major refactorings that would be in some way > better, but changing $loop_value to a reference gives the much more > readable: > > $loop_value['foo'] = some_func($loop_value['foo']); > $loop_value['bar'] = some_other_func($loop_value['bar'], true); > > References are fiddly, but they do have their uses. Short of eliminating > mutability, per functional programming, I think they'll always have their > place, in some form. > > Regards, > > -- > Rowan Collins > [IMSoP] >
Same here. I was just trying to keep my example simple. I agree that a generator, or even better array_map, would be a better way to deal with the simplistic example I gave.

Johannes Schlueter

9 years ago
On Fr, 2017-06-02 at 13:12 -0400, Michael Morris wrote:
> What about foreach by reference, which is honestly the only time I > use referencing anymore... > > foreach ($array as $key => &$value) { >   $value = someOp($value); > } > > Is this also bad?
If someOp() takes parameters by value this code disables copy-on-write and during the function call $value has to be duplicated. If the iteration would use values then copy-on-write can be effective and avoid copying. But for modification this indeed is a case where references might be useful, in the simplified example. foreach ($array as $key => &$value) {    $value++; } is nicer and faster than (at least in my expectation, haven't measured) foreach ($array as $key => &$value) {    $arry[$key] = $value+1; } Some might argue that using array_map() would be even nicer style, while then we have more function calls (even though internally cached lookups so they are a bit faster than direct function calls) For a larger and more realistic case the performance calculation becomes complicated, but often the extra copies cost more. But then again since PHP 7 for "simple types" a copy is relatively cheaper than before. (actually they don't have copy-on-write anymore, but references still need special treatment ...) johannes