Re: [PHP-DEV] [RFC] anti-coalescing-operator

2019-10-30 Thread Ken Stanley
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

2019-10-30 Thread Peter Bowyer
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

2019-10-25 Thread Claude Pache


> 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

2019-10-25 Thread Andreas Hennings
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

2019-10-25 Thread Andreas Hennings
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

2019-10-25 Thread Claude Pache

> 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

2019-10-25 Thread Rowan Tommins
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

2019-10-25 Thread Rowan Tommins
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

2019-10-25 Thread Claude Pache


> 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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Mike Schinkel
> 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

2019-10-24 Thread Mike Schinkel
> 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

2019-10-24 Thread Andreas Hennings
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

2019-10-24 Thread Andreas Hennings
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

2019-10-24 Thread Andreas Hennings
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

2019-10-24 Thread Sara Golemon
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

2019-10-24 Thread Sara Golemon
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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Kosit Supanyo
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

2019-10-24 Thread Mark Randall

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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Kosit Supanyo
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

2019-10-24 Thread Bruce Weirdan
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

2019-10-24 Thread Kosit Supanyo
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

2019-10-24 Thread 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

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



Re: [PHP-DEV] [RFC] anti-coalescing-operator

2019-10-24 Thread Rowan Tommins

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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Ken Stanley
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

2019-10-24 Thread Stephen Reay


> 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

2019-10-24 Thread Dan Ackroyd
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

2019-10-24 Thread Ken Stanley
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