Well, now the RFC has passed so congratulation on that one!

I can agree a bit that the RFC itself is a bit under specified,
but what to do about it? Some options:
- Expand it in the PHP documentation, but then the documentation
  becomes the master not the RFC itself.
- Update the RFC itself with some more examples, maybe not
  feasible given that the voting is over.
- Update RFC with link to Ruby.

What do you think? Anyway, I'm not so privy to the RFC process
so maybe this is a non issue...

Regards //Björn Larsson

Den 2016-03-25 kl. 13:46, skrev Midori Kocak:
http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html 
<http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html>

On 25 Mar 2016, at 13:42, Nikita Popov <nikita....@gmail.com> wrote:

On Fri, Mar 25, 2016 at 11:59 AM, Midori Kocak <mtko...@gmail.com 
<mailto:mtko...@gmail.com>> wrote:
Hi Everyone,

I think it's better idea to combine those two assignment operator RFC’s. So I 
am going to close the current one and open ??= with ?:=
What do you think? And we have to find better names.

Wishes,
Midori Kocak

I'd prefer to keep them separate, or at least keep their votes separate. The 
??= operator vote is currently unanimous at 24:0, while the ?:= vote was closed 
at something like 9:2, so there clearly are differences of opinion regarding 
these two operators.

I'll use this chance for some comments on the proposal. I can see the general 
usefulness of ??=, but right now the RFC is severely underspecified and I'm 
uncomfortable voting on it in it's current form as so much will depend on the 
final implementation. So, what do I mean by underspecified?

The only statement the RFC essentially makes is that $a ??= $b will be the same 
as $a = $a ?? $b, for variable-expression $a and expression $b. This statement, 
while a good high-level illustration, does not explain the exact behavior of 
this operator.

For example, consider the expression $a[print 'X'] ??= $b. A simple desugaring 
into $a[print 'X'] = $a[print 'X'] ?? $b will result in 'X' being printed 
twice. However, this is not how all other existing compound assignment 
operators behave: They will print X only once, as the LHS is only evaluated 
once. I assume that ??= would behave the same way.

However, with ??= the problem becomes more complicated. Let us assume that $a is an 
ArrayAccess object and consider the expression $a[0] ??= $b. Let us further assume 
that $x = $a->offsetGet(0) is non-null. Will $a[0] ??= $b result in a call to 
$a->offsetSet(0, $x)? This is what would normally happen with a compound 
assignment operator and what would be implied by the desugaring $a[0] = $a[0] ?? $b. 
However this assignment is not really necessary, as we're just reassigning the same 
value. So, does the call happen or not? Is the proper desugaring maybe if 
(!isset($a[0])) $a[0] = $b?

Let us now assume that $a is a recursive ArrayAccess object with by-reference 
offsetGet() and consider the expression $a[0][1] ??= expr. For a normal 
compound assignment operator, this would issue the call sequence

     $b = expr;
     $x =& $a->offsetGet(0);
     $y = $x->offsetGet(1);
     $y OP= $b;
     $x->offsetSet(1, $y);

Note that we only issue one offsetSet() at the end. We do not refetch $x via 
$a->offsetGet(0). How would the same work with the ??= operator? As the RHS is 
evaluated lazily, it is my opinion that only performing the offsetSet() call 
without refetching $x beforehand would violate PHP's indirection memory model. 
Additionally as ??= has to fetch offsets in BP_VAR_IS mode, we likely wouldn't be 
able to write them without refetching anymore.

So, what would be the desugared call sequence for $a[0][1] ??= expr? Something 
like this?

     if (!$a->offsetHas(0)) {
         goto assign;
     }
     $x = $a->offsetGet(0);
     if (x === null) {
         goto assign;
     }
     if (!$x->offsetHas(0)) {
         goto assign;
     }
     $y = $x->offsetGet(0);
     if ($y === null) {
         goto assign;
     }
     goto done;
assign:
     $b = expr;
     $x =& $a->offsetGet(0);
     $x->offsetSet(1, $b);
done:

That would be some first thoughts on the issue, though I'm sure there are more 
subtleties involved. I'd like to see the exact behavior of ??= (and ?:=) 
specified.

I'm also pretty sure that writing a patch for this will not be entirely easy. 
The combination of execute-once LHS side-effects and lazy RHS execution does 
not translate well to PHP's VM constraints.

Regards,
Nikita



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

Reply via email to