Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Wed, Oct 30, 2019 at 7:35 AM Peter Bowyer wrote: > On Fri, 25 Oct 2019 at 00:28, Sara Golemon wrote: > >> At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks >> ago (Javascript is making this one popular), and I threw together a rough >> PoC at >> https://github.com/php/php-src/compare/master...sgolemon:null-coalesce >> which >> I suspect he intends to RFC properly soon. As long as the topic is at >> hand, what's the general appetite for it? Should I bother polishing the >> turd? >> > > It would be the best Christmas present ever. > > Well. Almost. > > Peter > Folks, I haven't forgotten about this; in fact, I've been thinking about it all weekend, and I cannot come up with a good use-case that hasn't already been shown to have either a viable current work-around, or an RFC (with code already written) that would give me what I was looking to do with my !?? operator syntax. So, with that said, I see no reason to further the discussion on a not-null coalescing operator. I do want to thank everybody for their kind and thoughtful feedback. You really made me think about this, and I enjoyed it. I will continue to look for something I can cut my teeth on as a first-time contribution to php core. - Ken Stanley
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Fri, 25 Oct 2019 at 00:28, Sara Golemon wrote: > At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks > ago (Javascript is making this one popular), and I threw together a rough > PoC at > https://github.com/php/php-src/compare/master...sgolemon:null-coalesce > which > I suspect he intends to RFC properly soon. As long as the topic is at > hand, what's the general appetite for it? Should I bother polishing the > turd? > It would be the best Christmas present ever. Well. Almost. Peter
Re: [PHP-DEV] [RFC] anti-coalescing-operator
> Le 25 oct. 2019 à 04:36, Ken Stanley a écrit : > > So far it seems like the biggest concern(s) is that we would most likely > repeat the use of variables (nothing new), and that there are other ways to > do the same thing (again, nothing new). And of course the most valid > argument of all: adding more operators to the soup mix. Personally, I don’t > see these as show stoppers, at least given that the idea is not too wild > and out there. Hi, If you write A !?? B instead of isset(A) ? B : null you gain a *fixed* amount of 12 characters. The gain is proportionally low when A and B are not trivial expressions. (The difference is fixed, because the proposed operator does not allow to reduce possible repetition of expressions.) I don’t think that you gain readability or clarity. In particular, I am particularly confused with your last example: > /** > * @ParamConverter(name=“application”, ...) > */ > public function myAction(Request $request, Application $application) > { >$user = $application->getUser() !?? $this->getUser(); > > // ... do something with user, without worrying about it being null. > } because if $application->getUser() is null, then $user will be null, and you do have to worry about it being null, which makes me wonder whether there is some bug here. If it is really what you meant, spelling *null* explicitly will make it clearer, despite of being 12 characters longer. And if it is not what you meant, the bug will appear more readily: /** * @ParamConverter(name=“application”, ...) */ public function myAction(Request $request, Application $application) { $user = isset($application->getUser()) ? $this->getUser() : null; // ... do something with user, without worrying about it being null. (sic) } ―Claude
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Fri, 25 Oct 2019 at 12:27, Andreas Hennings wrote: > > On Fri, 25 Oct 2019 at 12:21, Rowan Tommins wrote: > > > > On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo wrote: > > > > > But I think this functionality should be of something like pipeline > > > operator: > > > > > > // send tmp variable to the next expression unconditionally > > > $ret = $_SERVER['fname'] |> $user->setName($$); > > > // send tmp variable to the next expression only when $_SERVER['fname'] is > > > set. > > > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > > > > > Also the syntax like above will be consistent with the proposed > > > safe-navigation operators. > > > > > > > > > I really like this idea, and it actually makes the pipeline operator itself > > feel more useful, too. > > > > Imagine this chain, where not only might the variable not be set, but it > > might not match a user, or the user might have no name: > > > > $upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName() > > ?|> strtoupper($$); > > > > As well as not needing to repeat the expression each time, as you would > > with an "anti-coalesce", "null-safe chain" feels a clearer reading of the > > intent here than "if not unset". > > I like this. > It is a bit like a temporary local variable. > > One limitation is that you only have one such pipe value at a time. > E.g. it would not cover this: > > return isset($a, $b) ? foo($a, $b) : null; > > or any nested parameters like foo(bar(baz())) where any intermediate > value could be null. Sorry, this last part is wrong of course. The pipe works great for nested calls. Just with multiple parameters which all can be null it does not. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Fri, 25 Oct 2019 at 12:21, Rowan Tommins wrote: > > On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo wrote: > > > But I think this functionality should be of something like pipeline > > operator: > > > > // send tmp variable to the next expression unconditionally > > $ret = $_SERVER['fname'] |> $user->setName($$); > > // send tmp variable to the next expression only when $_SERVER['fname'] is > > set. > > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > > > Also the syntax like above will be consistent with the proposed > > safe-navigation operators. > > > > > I really like this idea, and it actually makes the pipeline operator itself > feel more useful, too. > > Imagine this chain, where not only might the variable not be set, but it > might not match a user, or the user might have no name: > > $upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName() > ?|> strtoupper($$); > > As well as not needing to repeat the expression each time, as you would > with an "anti-coalesce", "null-safe chain" feels a clearer reading of the > intent here than "if not unset". I like this. It is a bit like a temporary local variable. One limitation is that you only have one such pipe value at a time. E.g. it would not cover this: return isset($a, $b) ? foo($a, $b) : null; or any nested parameters like foo(bar(baz())) where any intermediate value could be null. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
> Le 25 oct. 2019 à 01:23, Sara Golemon a écrit : > > Just testing the waters: Is there any appetite to have AND and OR behave > more like Pythons operator? > Instead of now: > (a or b) => bool(true) if either of a or b are true > (a and b) => bool(true) is either of a or b are true > > Behave as: > (a or b) => Value of a if true, b if a is not true but b is, bool(false) > otherwise. > (a and b) => Value of b if both are true, bool(false) otherwise. > Besides BC concerns, it is probably not a good idea to introduce (more) subtle differences between `and` and `&&`. That is, if you change `and`, you should change `&&` in the same direction. Maybe simply introduce the `!?:` operator?... Nevermind. —Claude
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, 24 Oct 2019 at 22:20, Kosit Supanyo wrote: > But I think this functionality should be of something like pipeline > operator: > > // send tmp variable to the next expression unconditionally > $ret = $_SERVER['fname'] |> $user->setName($$); > // send tmp variable to the next expression only when $_SERVER['fname'] is > set. > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > Also the syntax like above will be consistent with the proposed > safe-navigation operators. > I really like this idea, and it actually makes the pipeline operator itself feel more useful, too. Imagine this chain, where not only might the variable not be set, but it might not match a user, or the user might have no name: $upperCaseUserName = $_GET['user_id'] ?|> User::getById($$) ?-> getName() ?|> strtoupper($$); As well as not needing to repeat the expression each time, as you would with an "anti-coalesce", "null-safe chain" feels a clearer reading of the intent here than "if not unset". Regards, -- Rowan Tommins [IMSoP]
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Fri, 25 Oct 2019 at 03:37, Ken Stanley wrote: > This got rejected for being too large??? > If you trim the quotes in your replies to just the parts needed for context, it keeps the message shorter, and makes it much easier to read through. > > The fact that it’s a counterpart to an existing syntax l, I believe, > > further warrants it’s inclusion into the language. > As I mentioned before, it doesn't feel to me a very natural complement. The use cases for the new operator don't feel like "the negation" of the use cases for the existing ?? operator, and although different from null-safe calls, have more in common with them than "coalescing". > >> The repetition becomes more relevant if the expression we would repeat > >> is really long: > >> > >> isset($something['something']['something']['something']) !?? > >> $something['something']['something']['something']->foo(); > > > > > > This would be invalid because isset() returns Boolean I suspect that was just a mistake; the point was the new operator doesn't save any repetition in an expression such as: $something['something']['something']['something'] !?? $something['something']['something']['something']->foo(); Which in this particular case could be rewritten if we had a null-safe call operator, and would gain a lot more readability: $something['something']['something']['something']?->foo(); > > As far as flow control, let’s make no mistake, ??, ?:, and the idea of > !?? > > are all succinct forms of flow control. To pretend otherwise is a bit > > naive. > I think you're misunderstanding what people mean by "flow control"; the key point is whether you're using the operator to obtain a value, or to trigger a side effect. For instance, this would not generally be considered "flow control": $x = $someFlag ? 1 : 2; Yes, strictly speaking, you're selecting one of two paths, but the only side-effect is an assignment, outside the expression. Compare to this, where the value of the expression is never even used, and you're just choosing a side-effect: $someFlag ? deleteUser() : logOut(); Your second example was better in this respect, because it used the result: $user = $application->getUser() !?? $this->getUser(); However, is this actually the desired code? If I'm not mistaken, it would de-sugar to this: if ( isset($application->getUser() ) { $user = $this->getUser(); } else { $user = null; } Given that your specified aim is to look up a default, isn't this actually a case for the existing null-coalesce operator? $user = $application->getUser() ?? $this->getUser(); // or if the precedence is the other way around: $user = $this->getUser() ?? $application->getUser(); Regards, -- Rowan Tommins [IMSoP]
Re: [PHP-DEV] [RFC] anti-coalescing-operator
> Le 25 oct. 2019 à 04:31, Ken Stanley a écrit : > > If the parameter is null able, I may need to add an if condition to look up > a sane default value when the parameter comes through as null. It would be > much more succinct (and less error prone) to be able to say something like > > /** > * @ParamConverter(name=“application”, ...) > */ > public function myAction(Request $request, Application $application) > { >$user = $application->getUser() !?? $this->getUser(); > > // ... do something with user, without worrying about it being null. > } > Did you meant: $user = ($application ?? $this)->getUser(); ? —Claude
Re: [PHP-DEV] [RFC] anti-coalescing-operator
This got rejected for being too large??? On Thu, Oct 24, 2019 at 10:05 PM Ken Stanley wrote: > Now we’re talking. :-) > > This example is better indeed. >> But here I would prefer to have the ?-> operator proposed earlier >> (nullsafe calls). >> >> return $this->user?->getName(); >> > > Sure, but that limits you to use cases on the same object. With !?? You’d > be free to both use the same object, OR to use a different construct based > on a semantically related (but technically different) construct: $userId > !?? $this->getuser(); — It’s an example, so don’t get too hung up on the > color of the bike shed. > > >> >> >> >> 3. One purpose of the operator should be that you don't have to repeat >> >> the variable. Here you do, e.g. $_SERVER['fname'] >> >> >> > >> > I'm not sure how that's necessarily a bad thing. Would you elaborate? >> Is it simply a matter of writing the same characters twice? How is that >> different than: >> > >> > if (isset($_SERVER['fname'])) { >> > $user->setName($_SERVER['fname']); >> > } >> >> I thought you like brevity? "terse and simple"? >> Ofc it is not just about typing more characters, but about having two >> places that need to be updated if we change the value expression. >> All the arguments for DRY apply. >> > > To me, and I respect if this isn’t a popular opinion, DRY applies to > processes, logic, and constructs. Things like variables and non-logic is > (again imo) a step too far. > > In other words, the repetition of a variable name in a finite scope as > intended for this operator (ie within a line or two of each other) should > not be an argument for being DRY. > > Again, > > if (isset($_POST[‘field’]) { > $this->doSomething($_POST[‘field’]); > } > > Is absolutely no different than > > $_POST[‘field’] !?? $this->doSomething($_POST[‘field’]); > > And the same goes for $foo !?? $foo->getBar(); . > > >> And yes, with existing if/else code we would also have this kind of >> repetition for this use case. >> But if we introduce a new operator, we would expect this to go away, >> wouldn't we? > > > No. The aim is not to reduce variable usage. It’s to reduce boiler plate > code for a very common, and unnecessarily verbose coding pattern. In other > words, it’s syntactic sugar. > > Yes, I appreciate that “syntactic sugar” may be considered as a > four-letter word by some, but that does not dismiss the usefulness of such > syntax. > > The fact that it’s a counterpart to an existing syntax l, I believe, > further warrants it’s inclusion into the language. Why should t we have the > ability to do something when a value is not null? Why should we be forced > to be verbose about it? > > I refuse to accept the “this can be done using if’s or &&” argument, > simply because operators like ?? and ?: already exist. > > >> The repetition becomes more relevant if the expression we would repeat >> is really long: >> >> isset($something['something']['something']['something']) !?? >> $something['something']['something']['something']->foo(); > > > This would be invalid because isset() returns Boolean. ?? deals with > bulls, and naturally !?? deals with non-nulls. You’re thinking ?: which > deals with truthy/falsey values. That may be a separate (future) RFC. ;-) > > >> >> > >> >> >> >> 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']); >> > >> > >> > Ugh! I just noticed that I mistakenly did not update the method names >> for each line, so I can see how this might look like flow control. Those >> methods should be setFirstName, setLastName, setMiddleName, setPhone, and >> setEmail respectively. My apologies. >> >> I meant "only control flow" in the sense that we are not returning a >> value, or rather, we do not read the value. >> Ofc it makes a more lively example to have different methods, but I >> was looking past that already :) > > > Well thank you for the latitude. As much as I’d like to have written a > perfect informal proposal, I’m not that lucky. :-) > > As far as flow control, let’s make no mistake, ??, ?:, and the idea of !?? > are all succinct forms of flow control. To pretend otherwise is a bit > naive. Their entire existence is purely syntactic sugar so we do not have > keep writing the same boiler plate over and over. > > The goal here is to merely introduce a natural progression of ?? by > offering the ability to do something when a non-null value exists. I > understand it’s niche, but so is ?? for that matter. > > > >> >> > >> >> >> >> >> >> 2. >> >> Instead of "abusing" your new operator, you could simply "abuse" the >> >> old
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 8:54 PM Mike Schinkel wrote: > On Oct 24, 2019, at 6:49 PM, Ken Stanley wrote: > I would be keen to see the more expressive techniques that retain the > succinctness of having a not-null coalescing operator. > > > > When I read your first example, I immediately thought I would handle your > example in this way: > > $user->setFName( $_SERVER[ 'fname' ] ?? null ); > > $user->setLName( $_SERVER[ 'lname' ] ?? null ); > > $user->setMName( $_SERVER[ 'mname' ] ?? null ); > > $user->setPhone( $_SERVER[ 'phone' ] ?? null ); > > $user->setEmail( $_SERVER[ 'email' ] ?? null ); > > > Admittedly it does not require the functionality of your proposed > operator, and it delegates the null handling to the set*() methods, but it > is more succinct and does not require duplicating `$_SERVER[ '*' ]`, so > it would be a winner for me. > > The problem here is that null values may or may not be valid inputs for the setters. Assuming for one moment that the setters do allow null, what does that mean for the underlying model? Is null to mean that it’s under? Or is null just another possible value? Using !?? to only call a setter if there is a non-null value is very important in many circumstances - my original example was to illustrate a succinct way to implement a REST PATCH HTTP request, where only fields with values get updated - in other words, you don’t want to set other fields to null because you want to retain their original values; not overwrite them. Overwriting values with null is a valid use case, but not for this operator (not necessarily). Null means nothing, no value, or better: not answered. This is distinctly different than ‘’, false, or 0. Those are explicit responses to a question. Null Just means no data. > I also do not mind putting more effort into writing functions if it means > less effort required to call the functions. But maybe that is just me? > > But if you don’t have to, then why would you? I’m all for clarity and expressiveness. But I’m also for simplicity and being as succinct as practically possible. > Your 2nd example was more compelling for me, but Sara's nullsafe calls RFC > uses a syntax that is more clear and obvious to me. > > I am a Symfony developer, and as such I like to utilize annotations (bear with me). They have a ParamConverter annotation that can automatically look up an entity based on the type hint given to a controller action. If the parameter is null able, I may need to add an if condition to look up a sane default value when the parameter comes through as null. It would be much more succinct (and less error prone) to be able to say something like /** * @ParamConverter(name=“application”, ...) */ public function myAction(Request $request, Application $application) { $user = $application->getUser() !?? $this->getUser(); // ... do something with user, without worrying about it being null. } > Is there a 3rd or 4th use-case you have that are unlike the first two? > > I will let you know when I think of them. I totally understand how much easier it is for others to conceptualize with good examples. I want to be concise and relevant at the same time, and that’s actually pretty difficult. :-) > -Mike > > > > -- "Do not go gentle into that good night. Rage, rage against the dying of the light." — Dylan Thomas
Re: [PHP-DEV] [RFC] anti-coalescing-operator
> On Oct 24, 2019, at 6:49 PM, Ken Stanley wrote: > I would be keen to see the more expressive techniques that retain the > succinctness of having a not-null coalescing operator. When I read your first example, I immediately thought I would handle your example in this way: $user->setFName( $_SERVER[ 'fname' ] ?? null ); $user->setLName( $_SERVER[ 'lname' ] ?? null ); $user->setMName( $_SERVER[ 'mname' ] ?? null ); $user->setPhone( $_SERVER[ 'phone' ] ?? null ); $user->setEmail( $_SERVER[ 'email' ] ?? null ); Admittedly it does not require the functionality of your proposed operator, and it delegates the null handling to the set*() methods, but it is more succinct and does not require duplicating `$_SERVER[ '*' ]`, so it would be a winner for me. I also do not mind putting more effort into writing functions if it means less effort required to call the functions. But maybe that is just me? Your 2nd example was more compelling for me, but Sara's nullsafe calls RFC uses a syntax that is more clear and obvious to me. Is there a 3rd or 4th use-case you have that are unlike the first two? -Mike
Re: [PHP-DEV] [RFC] anti-coalescing-operator
> On Oct 24, 2019, at 8:03 PM, Andreas Hennings wrote: > > On Fri, 25 Oct 2019 at 01:28, Sara Golemon wrote: >> >> https://wiki.php.net/rfc/nullsafe_calls > > ?-> is a great idea. Totally agree, that would be nice. > The problem is this only works for method chaining, not for function > argument nesting. > So we might want something else in addition to that. > > foo(bar(baz() ???) ???); I am confused about this. Why would this be needed? In case the functions baz(), bar() or foo() do not exist? Please help me see what I am missing. -Mike
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, 24 Oct 2019 at 23:49, Ken Stanley wrote: > > On Thu, Oct 24, 2019 at 4:29 PM Andreas Hennings wrote: >> >> 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. > > > This argument can be made about ?? And ?:, which have already passed muster > and creates a precedent. But these were designed to produce a value, not for just control flow - see my other point. Yes, the same argument could have been made for those, if a similar example had been given to advertise their introduction. > Additionally, this is meant to compliment the existing ?? by adding a > negation counterpart (similar to how == has !== and > has <). > > I’m curious to what you find misleading about it? Its meant to literally be > the not-null coalescing operator. Misleading as in "look how much shorter this is". > >> >> 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. > > > Here is another example, not using them for flow control: > > > class Foo > { > /** > * @return User|null > */ > private $user; > > /** > * @return string|null > */ > public function getName(): ?string > { > return $this->user !?? $this->user->getName(); > } > } > > compared to: > > class Foo > { > /** > * @return User|null > */ > private $user; > > /** > * @return string|null > */ > public function getName(): ?string > { > // or $this->user instanceof User > return $this->user !== null ? $this->user->getName() : null; > } > } This example is better indeed. But here I would prefer to have the ?-> operator proposed earlier (nullsafe calls). return $this->user?->getName(); >> >> 3. One purpose of the operator should be that you don't have to repeat >> the variable. Here you do, e.g. $_SERVER['fname'] >> > > I'm not sure how that's necessarily a bad thing. Would you elaborate? Is it > simply a matter of writing the same characters twice? How is that
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Fri, 25 Oct 2019 at 01:28, Sara Golemon wrote: > > On Thu, Oct 24, 2019 at 12:46 PM Stephen Reay > wrote: > > > This sounds like an alternative approach (for solving the same basic > > problem) to the nullsafe operator discussed a while back, no? > > https://wiki.php.net/rfc/nullsafe_calls > > > > At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks > ago (Javascript is making this one popular), and I threw together a rough > PoC at > https://github.com/php/php-src/compare/master...sgolemon:null-coalesce which > I suspect he intends to RFC properly soon. As long as the topic is at > hand, what's the general appetite for it? Should I bother polishing the > turd? > > -Sara ?-> is a great idea. The problem is this only works for method chaining, not for function argument nesting. So we might want something else in addition to that. foo(bar(baz() ???) ???); -- Andreas -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Fri, 25 Oct 2019 at 01:24, Sara Golemon wrote: > > On Thu, Oct 24, 2019 at 4:55 PM Ken Stanley wrote: > > > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > > > > > Will return boolean. > > > > > > > Just testing the waters: Is there any appetite to have AND and OR behave > more like Pythons operator? Similar to javascript || and &&, although not exactly the same. > Instead of now: > (a or b) => bool(true) if either of a or b are true > (a and b) => bool(true) is either of a or b are true > > Behave as: > (a or b) => Value of a if true, b if a is not true but b is, bool(false) > otherwise. > (a and b) => Value of b if both are true, bool(false) otherwise. > > Coincidentally, this change to T_LOGICAL_AND would server OP's purpose. > > I'll tell ya, I'm leaning "No" because BC, but at the same time, AND/OR > seem to be underutilized constructs and I *suspect* (having done zero > research), that most existing uses would yield the same result as they do > now. At one point I started using these operators because they have different operator precedence than || and &&, allowing assignment in conditions without parentheses. I gave up on this only to comply with coding standards and to not confuse people. I would think we will make a lot of people angry if we change this. Imo, let's not. Besides, a lot of this can be achieved with the ?: ternary shortcut (not sure what's the name). > (a or b) => Value of a if true, b if a is not true but b is, bool(false) $a ?: ($b ?: false) === ($a ?: $b) ?: false === $a ?: $b ?: false > (a and b) => Value of b if both are true, bool(false) otherwise. $a ? ($b ?: false) : false === $a ? $b ?: false : false https://3v4l.org/q8Al9 It is a bit more verbose, I admit. But in most cases we don't need to replicate the exact behavior, and a simple ?: will do the trick. -- Andreas > > -Sara -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 12:46 PM Stephen Reay wrote: > This sounds like an alternative approach (for solving the same basic > problem) to the nullsafe operator discussed a while back, no? https://wiki.php.net/rfc/nullsafe_calls > > At the risk of hijacking, @matthewrask asked me about ?-> a couple weeks ago (Javascript is making this one popular), and I threw together a rough PoC at https://github.com/php/php-src/compare/master...sgolemon:null-coalesce which I suspect he intends to RFC properly soon. As long as the topic is at hand, what's the general appetite for it? Should I bother polishing the turd? -Sara
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 4:55 PM Ken Stanley wrote: > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > > > Will return boolean. > > > > Just testing the waters: Is there any appetite to have AND and OR behave more like Pythons operator? Instead of now: (a or b) => bool(true) if either of a or b are true (a and b) => bool(true) is either of a or b are true Behave as: (a or b) => Value of a if true, b if a is not true but b is, bool(false) otherwise. (a and b) => Value of b if both are true, bool(false) otherwise. Coincidentally, this change to T_LOGICAL_AND would server OP's purpose. I'll tell ya, I'm leaning "No" because BC, but at the same time, AND/OR seem to be underutilized constructs and I *suspect* (having done zero research), that most existing uses would yield the same result as they do now. -Sara
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 6:01 PM Mark Randall wrote: > On 24/10/2019 22:52, Ken Stanley wrote: > > I'm more interested in having a negation operator for the null-coalescing > > operator, especially since cognatively it should be easy to discern what > it > > does. > > At the point your syntax ends up looking like you're screaming at your > source code, I think easy cognition has likely gone out the window. > > There are plenty of much more expressive ways of doing this without > introducing new syntax IMHO. Mark, Yes, the operator would be new as in it doesn’t exist, but it’s not new in the fact that it is simply a negation of an existing operator. I would be keen to see the more expressive techniques that retain the succinctness of having a not-null coalescing operator. I can certainly appreciate the hesitation to introduce more syntax. However, I am arguing that this particular case is merely an extension (compliment) of the existing null-coalescing operator and therefore it’s not truly new; especially since !== null is a very common comparison used in programming. > > Mark Randall > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php Thank you. > `|>` is not something new it appeared in many languages long time ago (in some forms). JavaScript also has a proposal of it. And PHP someone has already proposed one. > https://github.com/tc39/proposal-pipeline-operator > https://wiki.php.net/rfc/pipe-operator Kosit, Thank you. In this case I’d still argue that my proposed operator, for what I’m intending it to be, is the better solution. I appreciate that my example might not have been the best, but I wanted to demonstrate one possible usage out of many that could be used to easily solve the same problem of needing to do “something” based on a non-null value. Thank you! -- "Do not go gentle into that good night. Rage, rage against the dying of the light." — Dylan Thomas
Re: [PHP-DEV] [RFC] anti-coalescing-operator
Hi Ken `|>` is not something new it appeared in many languages long time ago (in some forms). JavaScript also has a proposal of it. And PHP someone has already proposed one. https://github.com/tc39/proposal-pipeline-operator https://wiki.php.net/rfc/pipe-operator Cheers On Fri, Oct 25, 2019 at 4:53 AM Ken Stanley wrote: > > On Thu, Oct 24, 2019 at 5:19 PM Kosit Supanyo > wrote: > >> Hi Ken >> >> I totally agree with Andreas especially: >> >> One purpose of the operator should be that you don't have to repeat >>> the variable. Here you do, e.g. $_SERVER['fname'] >> >> >> But if this operator provide some way not to repeat the variable it will >> make sense. For example: >> >> $_SERVER['fname'] !?? $user->setName($$) >> > > I asked Andreas for their opinion on why this is bad in this context? > Especially since if I were to use a traditional ternary or if condition, > then I'd still be repeating the variable. > > >> >> But I think this functionality should be of something like pipeline >> operator: >> >> // send tmp variable to the next expression unconditionally >> $ret = $_SERVER['fname'] |> $user->setName($$); >> // send tmp variable to the next expression only when $_SERVER['fname'] >> is set. >> $ret = $_SERVER['fname'] ?|> $user->setName($$); >> >> Also the syntax like above will be consistent with the proposed >> safe-navigation operators. >> > > I'm more interested in having a negation operator for the null-coalescing > operator, especially since cognatively it should be easy to discern what it > does. I've personally not seen |>, and I'd be confused as to what it does > (e.g., is it a bitwise OR on a greater than comparison?). > > Thank you! The idea of $$ is neat, but not quite what I'm trying to > achieve here. If anything, wouldn't that facilitate a different RFC? > > - Ken Stanley > >
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On 24/10/2019 22:52, Ken Stanley wrote: I'm more interested in having a negation operator for the null-coalescing operator, especially since cognatively it should be easy to discern what it does. At the point your syntax ends up looking like you're screaming at your source code, I think easy cognition has likely gone out the window. There are plenty of much more expressive ways of doing this without introducing new syntax IMHO. Mark Randall -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 5:31 PM Kosit Supanyo wrote: > Hi Bruce > > If I understand correctly. > > $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); > > > Will return the result of $user->setName($_SERVER['fname']) if > $_SERVER['fname'] is set or null if not set. While: > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > > Will return boolean. > Yes. Semantically the same, but one is terse and the other is explicit. > > Cheers > >
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 5:19 PM Kosit Supanyo wrote: > Hi Ken > > I totally agree with Andreas especially: > > One purpose of the operator should be that you don't have to repeat >> the variable. Here you do, e.g. $_SERVER['fname'] > > > But if this operator provide some way not to repeat the variable it will > make sense. For example: > > $_SERVER['fname'] !?? $user->setName($$) > I asked Andreas for their opinion on why this is bad in this context? Especially since if I were to use a traditional ternary or if condition, then I'd still be repeating the variable. > > But I think this functionality should be of something like pipeline > operator: > > // send tmp variable to the next expression unconditionally > $ret = $_SERVER['fname'] |> $user->setName($$); > // send tmp variable to the next expression only when $_SERVER['fname'] is > set. > $ret = $_SERVER['fname'] ?|> $user->setName($$); > > Also the syntax like above will be consistent with the proposed > safe-navigation operators. > I'm more interested in having a negation operator for the null-coalescing operator, especially since cognatively it should be easy to discern what it does. I've personally not seen |>, and I'd be confused as to what it does (e.g., is it a bitwise OR on a greater than comparison?). Thank you! The idea of $$ is neat, but not quite what I'm trying to achieve here. If anything, wouldn't that facilitate a different RFC? - Ken Stanley
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 4:29 PM Andreas Hennings wrote: > 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. This argument can be made about ?? And ?:, which have already passed muster and creates a precedent. Additionally, this is meant to compliment the existing ?? by adding a negation counterpart (similar to how == has !== and > has <). I’m curious to what you find misleading about it? Its meant to literally be the not-null coalescing operator. > 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. Here is another example, not using them for flow control: user !?? $this->user->getName(); } } compared to: user instanceof User return $this->user !== null ? $this->user->getName() : null; } } > 3. One purpose of the operator should be that you don't have to repeat > the variable. Here you do, e.g. $_SERVER['fname'] > > I'm not sure how that's necessarily a bad thing. Would you elaborate? Is it simply a matter of writing the same characters twice? How is that different than: if (isset($_SERVER['fname'])) { $user->setName($_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']); Ugh! I just noticed that I mistakenly did not update the method names for each line, so I can see how this might look like flow control. Those methods should be setFirstName, setLastName, setMiddleName, setPhone, and setEmail respectively. My apologies. > > 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']); >
Re: [PHP-DEV] [RFC] anti-coalescing-operator
Hi Bruce If I understand correctly. $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); Will return the result of $user->setName($_SERVER['fname']) if $_SERVER['fname'] is set or null if not set. While: isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); Will return boolean. Cheers On Fri, Oct 25, 2019 at 4:24 AM Bruce Weirdan wrote: > Hi Ken > > > $_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']); > > What you described is already achievable with short-circuit && : > > isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); > > Besides, it's a widely used idiom known from shell scripting. > > -- > Best regards, > Bruce Weirdan mailto: > weir...@gmail.com > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
Re: [PHP-DEV] [RFC] anti-coalescing-operator
Hi Ken > $_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']); What you described is already achievable with short-circuit && : isset($_SERVER['fname']) && $user->setName($_SERVER['fname']); Besides, it's a widely used idiom known from shell scripting. -- Best regards, Bruce Weirdan mailto:weir...@gmail.com -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
Hi Ken I totally agree with Andreas especially: One purpose of the operator should be that you don't have to repeat > the variable. Here you do, e.g. $_SERVER['fname'] But if this operator provide some way not to repeat the variable it will make sense. For example: $_SERVER['fname'] !?? $user->setName($$) But I think this functionality should be of something like pipeline operator: // send tmp variable to the next expression unconditionally $ret = $_SERVER['fname'] |> $user->setName($$); // send tmp variable to the next expression only when $_SERVER['fname'] is set. $ret = $_SERVER['fname'] ?|> $user->setName($$); Also the syntax like above will be consistent with the proposed safe-navigation operators. Cheers On Fri, Oct 25, 2019 at 3:29 AM Andreas Hennings wrote: > 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 =
Re: [PHP-DEV] [RFC] anti-coalescing-operator
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 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
Hi Ken, This is definitely an interesting idea, and when described as "the opposite of ??" the !?? syntax makes sense. Looking at the example, though, the "negating" part becomes a bit confusing. The verbose form reads naturally as a positive assertion - "if this is set, do this": if (isset($_SERVER['fname']) { $user->setName($_SERVER['fname']); } If we used the ?? operator, it would be a negative, "if this is not set, do this": $_SERVER['fname'] ?? $user->unsetName(); So the short-hand form becomes a kind of double negative - "if this is not set, don't do this", or "if this is not not set, do this": $_SERVER['fname'] !?? $user->setName($_SERVER['fname']); That makes me think that the choice of syntax isn't quite right, but I'm not sure what to suggest instead. Regards, -- Rowan Tommins (né Collins) [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] anti-coalescing-operator
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 !??: 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 !??: 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
Re: [PHP-DEV] [RFC] anti-coalescing-operator
On Thu, Oct 24, 2019 at 1:46 PM Stephen Reay wrote: > Hi Ken, > > This sounds like an alternative approach (for solving the same basic > problem) to the nullsafe operator discussed a while back, no? > https://wiki.php.net/rfc/nullsafe_calls > > > Cheers > Stephen > Hi Stephen! Yes, it would be similar if the object you're testing against is the same object you want to call (e.g., $foo !?? $foo->getBar()). But, if the variable is not an object, or it's just a test for another object, then the nullsafe operator does not seem to address this situation (e.g., $userId !?? $bar->getUser($userId())). In fact, I could see this RFC complimenting the nullsafe operator: $userId !?? $bar->getUser($userId)?->getName(). Thank you, Ken Stanley PS. Dan, I am going to respond to your request for a code example; I am taking my time so that I can give you and everyone else a good example. :)
Re: [PHP-DEV] [RFC] anti-coalescing-operator
> On 25 Oct 2019, at 00:33, 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 > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > Hi Ken, This sounds like an alternative approach (for solving the same basic problem) to the nullsafe operator discussed a while back, no? https://wiki.php.net/rfc/nullsafe_calls Cheers Stephen
Re: [PHP-DEV] [RFC] anti-coalescing-operator
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 -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] [RFC] anti-coalescing-operator
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? You're left with the traditional (and sometimes verbose) methods of using if conditions or the full-blown ternary operator `$foo !== null ? : null;`. I am here to gauge the interest of the community in having an anti-coalescing operator that would execute code only if the condition is not null, otherwise returning null in its stead. If this is not a wholly terrible idea, I will -- as suggested -- then continue to create an official RFC. My initial thought process would be to use a similar syntax to the Null Coalescing Operator (??), but to add negation: `$bar = $foo !?? $foo->getBar()`. I didn't want to use `!?` because then if anybody wanted to add an anti-ternary operator (e.g., `!?:`) for falsey comparison, then they'd have to get creative or use the three-character approach I am already proposing. The purpose is simply to negate the existing behavior, so at first glance I do not see any BC breakages or additional complexities that haven't already been addressed - naturally, I could be wrong. The driving use case, as hinted at in my above example, is if I have a nullable object I only want to call a method on it if the object is not null. Otherwise, default to the null value. I am working through the RFC Howto [https://wiki.php.net/rfc/howto], and it suggests that I ask for wiki karma for my account (897syudjhf) so that I may create the RFC when appropriate. Additionally, I have not [yet] found any existing precedence for anti-coalescing; i.e., there does not seem to be an elegant counterpart to COALESCE() in SQL. And, as they say, naming is hard. If `anti-coalescing-operator` does not sit well with you all, I am open to naming suggestions. Thank you for your time, Ken Stanley