On Thu, 24 Oct 2019 at 20:59, Ken Stanley <doh...@gmail.com> wrote:
>
> On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd <dan...@basereality.com> wrote:
>
> > On Thu, 24 Oct 2019 at 18:21, Ken Stanley <doh...@gmail.com> wrote:
> > >
> > > Since PHP 7.0 brought forward the Null Coalescing Operator (??), writing
> > > more succinct code for how to handle null values has been a blessing.
> > But,
> > > what about the inverse when you want to do something when a value is not
> > > null?
> >
> > Hi Ken,
> >
> > It may help to give a real world example, rather than a metasyntactic
> > one, as I can't immediately see how this would be useful.
> >
> > People have been expressing a concern over 'symbol soup' for similar
> > ideas. The null colalesce scenario happens frequently enough, that it
> > seemed to overcome the hurdle needed for acceptance. Again, giving a
> > real world example of what you currently need to do frequently might
> > help other people understand the need.
> >
> > cheers
> > Dan
> >
>
> Hi Dan,
>
> After some thought, and searching through my existing code bases, I believe
> I've come up with a decent code example to help demonstrate the usefulness
> of the proposed anti-coalescing-operator:
>
> Without !??:
> <?php
>
> class ExampleController
> {
>     /**
>      * PATCH a User object.
>      */
>     public function saveAction(int $userId)
>     {
>         $user = $this->getUser($userId);
>
>         if (isset($_SERVER['fname']) {
>             $user->setName($_SERVER['fname']);
>         }
>
>         if (isset($_SERVER['lname']) {
>             $user->setName($_SERVER['lname']);
>         }
>
>         if (isset($_SERVER['mname']) {
>             $user->setName($_SERVER['mname']);
>         }
>
>         if (isset($_SERVER['phone']) {
>             $user->setName($_SERVER['phone']);
>         }
>
>         if (isset($_SERVER['email']) {
>             $user->setName($_SERVER['email']);
>         }
>
>         $this-saveUser($user);
>     }
> }
>
> With !??:
> <?php
>
> class ExampleController
> {
>     /**
>      * PATCH a User object.
>      */
>     public function saveAction(int $userId)
>     {
>         $user = $this->getUser($userId);
>
>         $_SERVER['fname'] !?? $user->setName($_SERVER['fname']);
>         $_SERVER['lname'] !?? $user->setName($_SERVER['lname']);
>         $_SERVER['mname'] !?? $user->setName($_SERVER['mname']);
>         $_SERVER['phone'] !?? $user->setName($_SERVER['phone']);
>         $_SERVER['email'] !?? $user->setName($_SERVER['email']);
>
>         $this-saveUser($user);
>     }
> }
> Thank you,
> Ken Stanley

Not convinced.
1. Most of the perceived brevity is from omitting line breaks and
curly brackets, which is a bit misleading imo.
2. It is not the intended use of these kinds of operators (ternary or
null coalesce). Normally you would use them to produce a value, here
you use them for control flow only.
3. One purpose of the operator should be that you don't have to repeat
the variable. Here you do, e.g. $_SERVER['fname']

1.
If you would simply omit the line breaks in the first version, you
would get this:

    if (isset($_SERVER['fname'])) $user->setName($_SERVER['fname']);
    if (isset($_SERVER['lname'])) $user->setName($_SERVER['lname']);
    if (isset($_SERVER['mname'])) $user->setName($_SERVER['mname']);
    if (isset($_SERVER['phone'])) $user->setName($_SERVER['phone']);
    if (isset($_SERVER['email'])) $user->setName($_SERVER['email']);

2.
Instead of "abusing" your new operator, you could simply "abuse" the
old ternary ?: instead:

    !isset($_SERVER['fname']) ?: $user->setName($_SERVER['fname']);
    !isset($_SERVER['lname']) ?: $user->setName($_SERVER['lname']);
    !isset($_SERVER['mname']) ?: $user->setName($_SERVER['mname']);
    !isset($_SERVER['phone']) ?: $user->setName($_SERVER['phone']);
    !isset($_SERVER['email']) ?: $user->setName($_SERVER['email']);

3.
One way to not repeat the variable would be to introduce a temporary
local variable, like so:

    if (NULL !== $fname = $_SERVER['fname'] ?? NULL) $user->setName($fname);

This gets more useful if the variable expression is something longer.

A new language feature for this purpose could have an anatomy like this:
https://3v4l.org/TjuuO or
https://3v4l.org/U6arm

and the short syntax would be like so:

   $product = ($x ??! NULL) * ($y ??! NULL);

or the NULL can be omitted:

   $product = ($x ??!) * ($y ??!);

So, the operator would break out of the current expression context,
and produce a value one level up, a bit like a try/throw/catch would,
or like a break in switch.

This is just a basic idea, it still leaves a lot of questions open.
If the expression context is multiple levels deep, how many of these
levels are we breaking?

I am not suggesting this is a good idea, but I think it is an
improvement to the original proposal.

-- Andreas

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

Reply via email to