Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:107669 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 87592 invoked from network); 24 Oct 2019 22:43:00 -0000 Received: from unknown (HELO php-smtp3.php.net) (208.43.231.12) by pb1.pair.com with SMTP; 24 Oct 2019 22:43:00 -0000 Received: from php-smtp3.php.net (localhost [127.0.0.1]) by php-smtp3.php.net (Postfix) with ESMTP id 5DC7A2D1FC8 for ; Thu, 24 Oct 2019 13:29:29 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp3.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS3215 2.6.0.0/16 X-Spam-Virus: No Received: from mail-qk1-x730.google.com (mail-qk1-x730.google.com [IPv6:2607:f8b0:4864:20::730]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp3.php.net (Postfix) with ESMTPS for ; Thu, 24 Oct 2019 13:29:28 -0700 (PDT) Received: by mail-qk1-x730.google.com with SMTP id y189so24721613qkc.3 for ; Thu, 24 Oct 2019 13:29:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dqxtech-net.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=kFfFM+9epBWrkYfFDEaZKwqOg32r5z2Rugl0EvwYvZc=; b=PFwMdocwOMy6bkvXNc2FLqqP2IlQgWGuklh0Wxr6DZze7Ty5xNZfhjUtVLrQcU/ojx R2UjvgyAVZ9E3WU7ohXDAQ2p3lqkgdCS8TVcLJ98Caxd9vHfwu/qTUOqvhK/EECHLuTG AMxQ4jT5FX3kvoeJpOCUgZJNOaUmyp2pgQVJXlURAgdSniBtc+zmPWetOlgS6hxAGSvu Guk42DNGMWLoJC8dyZKHdeRQxg/j6K6GVo1aewSmDYbwOmdk9bod9MnSgzu3swz2xZo3 3BGf5zHLi9aqwu6WesUBjUXRio1QUJwVRiQ8NGhmqwMwCN+GItMdpaUOqulKNGSMN5oa vpOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=kFfFM+9epBWrkYfFDEaZKwqOg32r5z2Rugl0EvwYvZc=; b=DcC7L4a5o7JPSNQhNItNneMWhLfezHdxmjtjxZEkUjv9JuqD9DX4xNcNKgGWE+s6HF PS2o6A6DODboBvzim7W7f4ZVFLFGLb6KILeDyGFv+He80DuS9MTu1c8BUil4dKnrr6Ix 1aqeRy+G58dx2F16EFCe2SCPkavuaPVjjzJD3Abd4YzlrGZnuODals7V160fKpfW09+M UYiV/gOby3wc0Wj3azZ0MseKzXW3wabBcWhPOeo+30wD48Qmx2oI/Mu1F8vHLJ/DiuVk UkM027n9t8Ey1XxI9rBhZ4uwq+Iy8lwdx0krc6wfDlpPeP9bxcYVwuzcnQ4VHhUQTSma Xoqg== X-Gm-Message-State: APjAAAWuiWKKeeVoUQr7qxKDbkWGIvhxrXn+Tcal/orsx4ecrmbwgoWT Ih9cS4KoclzODoa8HduuB7dcrllnQNw= X-Google-Smtp-Source: APXvYqz3zy1PYiVRplXhjdrPKwo0PgXTl1GSLrsmqqMk2Nzw8Up7E/UuJWw9J+s+vRYfUzZ/jrb3uw== X-Received: by 2002:a37:2795:: with SMTP id n143mr3384407qkn.328.1571948967770; Thu, 24 Oct 2019 13:29:27 -0700 (PDT) Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com. [209.85.160.173]) by smtp.googlemail.com with ESMTPSA id u18sm12996691qth.20.2019.10.24.13.29.26 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 24 Oct 2019 13:29:27 -0700 (PDT) Received: by mail-qt1-f173.google.com with SMTP id w14so39836692qto.9 for ; Thu, 24 Oct 2019 13:29:26 -0700 (PDT) X-Received: by 2002:a05:6214:1887:: with SMTP id cx7mr16803943qvb.123.1571948966470; Thu, 24 Oct 2019 13:29:26 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Thu, 24 Oct 2019 22:29:15 +0200 X-Gmail-Original-Message-ID: Message-ID: To: Ken Stanley Cc: Dan Ackroyd , PHP internals Content-Type: text/plain; charset="UTF-8" X-Envelope-From: Subject: Re: [PHP-DEV] [RFC] anti-coalescing-operator From: andreas@dqxtech.net (Andreas Hennings) On Thu, 24 Oct 2019 at 20:59, Ken Stanley wrote: > > On Thu, Oct 24, 2019 at 1:33 PM Dan Ackroyd wrote: > > > On Thu, 24 Oct 2019 at 18:21, Ken Stanley 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 !??: > > 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 !??: > > 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