August 24, 2020
On Monday, 24 August 2020 at 12:34:13 UTC, Adam D. Ruppe wrote:
> On Monday, 24 August 2020 at 12:28:27 UTC, Stefan Koch wrote:
>> 2) Adding a special syntax for what I perceive to be an uncommon case
>
> This is a very common case because void is frequently special cased. You cannot have a local variable of type void meaning any time you want to work with a generic function return value, you can't just be like `T ret = call(); return ret;`, you must check if T != void before doing that.
>
> What I usually do though is static if(is(T == void)) call(); else { ret = call(); /* process ret */ return ret; } but it is obnoxious to duplicate that call every time still.
>
> Lots of Phobos things also return void as the special case of "not found".
>
> What I'd love is if we didn't have to special case void all the time... but we do, making some variant of this specific check pretty common.

I see.
So `T != void` is special because it doesn't really play well with the other types.

That clarifies the motivation.

Thanks for explaining Adam.
August 24, 2020
On 24.08.20 13:49, Steven Schveighoffer wrote:
>>
> 
> Yes. If you write !is(T == void), then you are already not checking whether T is defined. This is no different.
> 

So far the pattern is `is(S op T)`. It checks whether S is a valid type and then checks `S op T`.

> This literally is just a nicer way to write it, where the operation is closer to the parameters, instead of partly outside the expression.

(I think the implications any of this has for the compiler implementation or the user experience has been greatly exaggerated.)
August 24, 2020
On 8/24/20 1:17 PM, Timon Gehr wrote:
> On 24.08.20 13:49, Steven Schveighoffer wrote:
>>>
>>
>> Yes. If you write !is(T == void), then you are already not checking whether T is defined. This is no different.
>>
> 
> So far the pattern is `is(S op T)`. It checks whether S is a valid type and then checks `S op T`.

But op is only '==' or ':', which are in sync with the requirements without needing the first part (if S is invalid, then obviously it can't equal T, or be convertible to T). We have room to add other ops that might have a slightly different behavior.

That being said, if it could be added so is(S != T) is false if S is invalid I wouldn't object.

> 
>> This literally is just a nicer way to write it, where the operation is closer to the parameters, instead of partly outside the expression.
> 
> (I think the implications any of this has for the compiler implementation or the user experience has been greatly exaggerated.)

The problem is usually something like:
static if (!is(Some!(Long!(Chain, Of, Template, Parameter, Data) == int));

At a glance, seeing that initial '!' among the various instantiation '!', and associating it with the check at the very end '==', is difficult for code review.

It's ok, it's just not ideal in terms of focusing the reader on the operation at hand.

This isn't a must-have, it's just something that has annoyed me multiple times (where I am reading code, trying to figure out why it's doing what it's doing, and then realize I missed the '!' at the front).

Really, all the arguments for having '!=' for binary operations vs doing !(someExpr == otherExp) apply here. I also really don't find the "it will complicate the compiler" arguments convincing.

-Steve
August 24, 2020
On 24.08.20 19:36, Steven Schveighoffer wrote:
> 
> Really, all the arguments for having '!=' for binary operations vs doing !(someExpr == otherExp) apply here.

Some, not all (you are not getting rid of parentheses).

> I also really don't find the "it will complicate the compiler" arguments convincing. 

If it does so meaningfully, it's probably an issue with the chosen implementation strategy.
August 25, 2020
On Monday, 24 August 2020 at 12:28:27 UTC, Stefan Koch wrote:
> 1) Complicating the rules for is expressions further

It will complicate a lot more since, you can do type matching chains in is expression:

------
is(T : Z[], Z != X, X : SomeType)
------

- Alex
August 25, 2020
On 8/25/20 3:12 AM, Alexandru Ermicioi wrote:
> On Monday, 24 August 2020 at 12:28:27 UTC, Stefan Koch wrote:
>> 1) Complicating the rules for is expressions further
> 
> It will complicate a lot more since, you can do type matching chains in is expression:
> 
> ------
> is(T : Z[], Z != X, X : SomeType)
> ------
> 

That doesn't look valid according to the grammar. Or if it passes, it may not do what you think it does. You sure this works?

-Steve
August 26, 2020
On Tuesday, 25 August 2020 at 12:55:34 UTC, Steven Schveighoffer wrote:
> On 8/25/20 3:12 AM, Alexandru Ermicioi wrote:
>> On Monday, 24 August 2020 at 12:28:27 UTC, Stefan Koch wrote:
>>> 1) Complicating the rules for is expressions further
>> 
>> It will complicate a lot more since, you can do type matching chains in is expression:
>> 
>> ------
>> is(T : Z[], Z != X, X : SomeType)
>> ------
>> 
>
> That doesn't look valid according to the grammar. Or if it passes, it may not do what you think it does. You sure this works?
>
> -Steve

Ah, sorry for bad english. It should be "could do type matching" not "can". If support for negation is added inside is expression, then it should also be supported in such chains as above, not just the simplest case as suggested by other people in this discussion.
August 26, 2020
On 8/26/20 3:52 AM, Alexandru Ermicioi wrote:
> On Tuesday, 25 August 2020 at 12:55:34 UTC, Steven Schveighoffer wrote:
>> On 8/25/20 3:12 AM, Alexandru Ermicioi wrote:
>>> On Monday, 24 August 2020 at 12:28:27 UTC, Stefan Koch wrote:
>>>> 1) Complicating the rules for is expressions further
>>>
>>> It will complicate a lot more since, you can do type matching chains in is expression:
>>>
>>> ------
>>> is(T : Z[], Z != X, X : SomeType)
>>> ------
>>>
>>
>> That doesn't look valid according to the grammar. Or if it passes, it may not do what you think it does. You sure this works?
>>
> 
> Ah, sorry for bad english. It should be "could do type matching" not "can". If support for negation is added inside is expression, then it should also be supported in such chains as above, not just the simplest case as suggested by other people in this discussion.


No worries! My point actually was that I don't think such "chains" are valid, even without the !=. Do you have a valid case that works today (without !=)?

-Steve
August 27, 2020
On Wednesday, 26 August 2020 at 11:44:22 UTC, Steven Schveighoffer wrote:
> No worries! My point actually was that I don't think such "chains" are valid, even without the !=. Do you have a valid case that works today (without !=)?
>
> -Steve

Well, you're right, it doesn't work even with ==, right now. I was pretty sure it should've worked. Seems that ==, is only allowed as first element in a 'is' chain, which is counter-intuitive.

- Alex.
August 28, 2020
On Sunday, 23 August 2020 at 21:08:30 UTC, Per Nordlöw wrote:
> Why aren't more operators allowed inside `is(...)`-expressions?
>
> For instance
>
>     if (!is(CommonType!(typeof(min), typeof(max)) == void))
>
> could be written as
>
>     if (is(CommonType!(typeof(min), typeof(max)) != void))
>
> .

There is one expression where allowing “!” would be much more beneficial — version condition. Currently we are forced to write something like:
    version (OSX) {} else {
        /* ... */
    }
when it could be just:
    version (!OSX) {
        /* ... */
    }
I am aware that it was Walter’s intention to make the version syntax simplistic, but I don’t think that allowing “!” would do any harm.