> On Feb 23, 2020, at 2:00 AM, Mike Schinkel <m...@newclarity.net> wrote:
> On Feb 22, 2020, at 5:56 AM, Rowan Tommins <rowan.coll...@gmail.com> wrote:
>> One of the reasons it is confusing is because developers are currently
>> required to use the ampersand in one place and not the other.  Making
>> it always used removes said confusion as they would no longer be a
>> reason to have to remember when and when not to use the ampersand
>> anymore.
> 
> Maybe. I think a larger part of it is that references themselves are a 
> slightly confusing concept, and the fact that & looks like an operator of its 
> own (and is often documented that way) but is really an annotation on other 
> operators/commands. That is, the & in $foo = &$bar and return &$bar doesn't 
> modify $bar, it modifies = and return, respectively.
> 
> Making the rules more logical and symmetrical would perhaps be more helpful 
> to new users than it is to established users, particularly those who've known 
> multiple versions of the language already.

You call out the use of the ampersand being viewed as an operator acting on a 
variable as problematic, but that is already baked into current PHP, not going 
to change any time soon if ever, and is orthogonal to this RFC. 

So whether or not people find the ampersand operator to be confusing that is 
irrelevant to the debate posed by Nikita's RFC over whether we should make the 
use of ampersand related to passing-by-reference be more consistent.

>> There is a potential "PR" cost of this change that should be weighed
>> against the advantages.
>> 
>> To say "We fixed something that in hindsight we've since determined was
>> a problem." How is this a concern? 
> 
> The concern is that the costs will be much more visible to users than the 
> benefits, and they will resent the core developers pushing that requirement 
> onto them, rather than thanking then for their hard work.
> 
> As I said, that's not an absolute reason not to do it, it's a cost to be 
> weighed.

Nikita's RFC proposes that the ampersand would be optional at the calling site, 
so is it really a concern that developers will resent something that is 
optional?

Yes Nikita mentioned that a future "edition" might make is a requirement, but 
even then it will still be optional — developers can choose not to use the new 
edition — and I think the resentment will come more from the concept of forcing 
an "edition" on developers than any specific feature.  Note that I plan to post 
soon about how I think we can alleviate that.

So we can debate the PR "cost" of requiring ampersands at the call site when 
the requiring RFC is on the table.

As a side note, I remember thinking "WTF?!?" when the requirement to use an 
ampersand at the calling site was removed. It is possible your analysis of PR 
cost is discounting the potential large number of people who will think adding 
it back is a good think.

>>> I'm also not very keen on internal functions being able to do things
>> that can't be replicated on userland, and this RFC adds two: additional
>> behaviour for existing "prefer-ref" arguments, and new "prefer-value"
>> arguments
>> 
>> So what specific problems would having these enhancement cause for the
>> language?
> 
> There are two problems I have with internal-only features in general: the 
> inability to polyfill and extend, and the requirement for a separate mental 
> model.
> 
> As an example of the first, the RFC mentions using call_user_func with a 
> call-site annotation to forward the parameter by reference. The reason for 
> allowing that also applies to a user-defined wrapper like 
> call_with_current_user or call_with_swapped_parameters, but there's no syntax 
> for those to be marked "prefer-val".

Let's analyze.  

In this case there does not appear to be a need for "prefer-val."   And 
Nikita's RFC adds functionality we currently do not have — ability to pass by 
reference to call_user_func() so that is a win over status quo as it gains a 
feature that we previously internal-only:

<?php
function current_user():int {
   return 1;
}
function foobar( int $current_user, int &$foo, int $bar ) {
   $foo++;
   $bar++;
}
function call_with_current_user(Callable $callable, int &$foo, int $bar ) {
   return call_user_func( $callable, current_user(), &$foo, $bar );
}
$foo = 0;
$bar = 0;
call_with_current_user( 'foobar', &$foo, $bar );
echo $foo;  // prints 1
echo $bar;  // prints 0

Now if you want to use call_user_func_array() then I agree we are missing 
functionality. Consider this example which envisions a new function called 
`func_is_byref_arg()`. Yes the function name is a horrible name but consistent 
with existing functions for related purposes:

<?php
function current_user():int {
   return 1;
}
function foobar( int $current_user, int ...&$args ) {
   foreach( $args as $i => $f ) {
      $args[$i]++;
   }
}
function call_with_current_user(Callable $callable, int ...&$args ) {
   array_unshift(&$args,current_user());
   $temp_args = $args;
   $result = call_user_func_array( $callable, &$temp_args );
   foreach( $temp_args as $i => $t ) {
      if ( func_is_byref_arg( $i, $args ) ) {
         $args = $temp_args[$i];
      }
      
   }
   return $result;
}
$foo = 0;
$bar = 0;
$baz = 0;
call_with_current_user( 'foobar', &$foo, $bar, $baz );
echo $foo;  // prints 1
echo $bar;  // prints 0
echo $baz;  // prints 0

In my example func_is_byref_arg($pos[,$variadic_arg]):bool accepts one 
parameter if you are checking for by-ref positionally, and two if you are 
introspecting a variadic parameter.

So I argue we should fill in the holes of the RFC that introduces a feature 
that to help developers write more robust code instead of decline an RFC for 
imperfections in its first draft.

> As an example of the second, even under strict settings, calls to certain 
> internal functions will have an optional & at the call site, which changes 
> their behaviour.
> 
> To those without knowledge of the core, those functions simply have to be 
> remembered as "magic", because their behaviour can't be modelled as part of 
> the normal language.

I am unclear how the optional ampersand at the call site will change the 
behavior.  

As I understand the RFC the behavior will still be driven by the ampersand at 
the declaration site. The presence or absence of ampersand at a call still will 
merely be decoration that allows developers to better convey their intent.

Can you please give an example of how this RFC would change behavior at call 
site compared to a call site where the ampersand did not exist, given the 
behavior of this RFC?

>>> My current opinion is that I'd rather wait for the details of out and
>> inout parameters to be worked out, and reap higher gains for the same
>> cost. For instance, if preg_match could mark $matches as "out", I'd be
>> more happy to run in a mode where I needed to add a call-site keyword.
>> 
>> This sounds like preferring perfect in the (potentially distant) future
>> vs. much better today.
> 
> 
> No, it's preferring to hold out for a little bit more value to weigh against 
> my evaluation of the cost. 
> 
> This is, when followed through to its conclusion of mandatory marking, a 
> disruptive change to every piece of code, so we need to decide if the 
> disruption is worth it. 

That is disingenuous.  The RFC does not require mandatory use, period.  

The "cost" you worry about will not exist unless and until a future RFC 
proposes to make it mandatory and that RFC is accepted.

Further, your cost analysis does not appear to consider the cost of status quo 
and this RFC's ability to reduce that cost.

Using Nikita's RFC example there is a potential real-world cost to getting the 
following wrong in a userland project:

$ret = array_slice($array, 0, 3);
$ret = array_splice($array, 0, 3);

With Nikita's RFC developers could chose to start using ampersand at the 
calling site for these type of methods. Let's consider that I write the 
following:

array_slice(&$array, 0, 3);
array_splice(&$array, 0, 3);

With this RFC (I assume) an error could be generated on array_splice(&$array, 
0, 3)saying that I cannot pass the array by reference.  Today we don't get 
that. This alone could reduce errors that I have seen in source code and I 
admittedly have committed myself.

Said succinctly, there is a (IMO significant) cost to doing nothing that your 
analysis appears to ignore.

> It's also the second change in the same place, and we should be sure that 
> we've got it right this time, and won't require a third change in the near 
> future. 

I don't particularly see a problem with requiring a third change in the future. 
Hindsight is a wonderful clarifier.  And I believe elsewhere you have been 
debating me over the need for incremental change. Caveat emptor.

> For instance, if out parameters were added, would the same line of code end 
> up going from optional &, to forbidden &, to mandatory &, to mandatory "out"? 

My view is that we should actually hash those concerns out and move forward 
rather than state them in the abstract and let the fact that legitimate 
concerns *might* exist derail an improvement to the language.

Since there are not infinite potentials, let's just address your specific 
concerns here. My straw man proposal is that if we add an `out` keyword exists 
then a developer could use either `out` or `&` but not both. Then in a future 
"edition" of pHP it would be possible that we disallow `&` if enough people 
agree that that is better.  Or we could leave as either/or.  Allowing ampersand 
at a call site today does not block potential future `out` keywords AFAICT.

For me I don't care which it is as long as there is a calling site notation 
that allows a developer to write code indicating intent and for other 
developers to read code and see that intent. 

Status quo waiting for some future potential that may not arrive for years does 
not get us there in the near term, but Nikita's RFC would.


> I'm not strongly against the idea, but the advantages just don't feel quite 
> strong enough, so if I had a vote, I'd currently be inclined to vote no.

Heh. My vote would yes. And since neither of us have a vote I guess it would be 
applicable to say they cancel each other's vote out.  Or not.  :-D

-Mike

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to