Tests for null coalescing assignment operator
| From: | Midori Kocak | Date: | Sun, 03 Apr 2016 01:17:32 +0000 |
| Subject: | Tests for null coalescing assignment operator | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-92073@lists.php.net to get a copy of this message | ||
Dear All,
Based on the concerns I wrote some tests. Can you check those and give feedback? Also, in ruby, $a
||= $b, the implementation is not equal to $a = $a || $b, but is equal to $a || $a = $b; I am a
little bit confused, I am not entirely sure, but I guess this approach would solve our problems.
https://gist.github.com/midorikocak/abc9fd9b6ca30359d201bc859edba9ee
<https://gist.github.com/midorikocak/abc9fd9b6ca30359d201bc859edba9ee>
We can use these examples as the part of the new documentation and as a guideline for implementation
tests. Can you add also any extreme cases that should raise errors to my test?
Yours,
Midori
> On 25 Mar 2016, at 13:42, Nikita Popov <nikita.ppv@gmail.com> wrote:
>
> On Fri, Mar 25, 2016 at 11:59 AM, Midori Kocak <mtkocak@gmail.com
> <mailto:mtkocak@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