50 comments

[ 3.2 ms ] story [ 113 ms ] thread
I struggle to find a simple, canonical example where that kind of condition could be useful. The examples in the paper seem a bit remote to me.

Anyone came up with some enlightening examples?

I think it could be really useful for assertions.

assert(someObj => someObj.data);

The cannonical way to write that currently would likely be something like:

if (someObj) assert(someObj.data);

I think the more canonical way would be

assert(!someObj || someObj.data);

Which seems fine as it is.

> Which seems fine as it is.

I don’t know you, but I guess that’s because of familiarity from years of seeing this kind of thing.

I think “=>” is clearer because it is what (AFAIK) people learn at school.

Sure, we learned "p => q" in discrete math, but we also learned "assert(someObj && someObj.data)" in CS101 or CS102. I think you're right, it is clearer, but not worth sacrificing the near universal familiarity of boolean expressions. I'd accept a change like this in Python, but it feels out of place in C++.
Python _really_ doesn't need more obtuse syntax. It's bad enough as it is.
Old comment, but that's not quite right. The equivalent for implication is "assert(!someObj || someObj.data)" which is much more confusing to read. It's saying if someObj exists, then it should also have data. Upon reflection, I think a better example would be something like "assert(someObj.type == SomeObjType::Float => !isnan(someObj.data))". Without the new operator, it would be "assert(someObj.type != SomeObjType::Float || !isnan(someObj.data))" which doesn't make the intent clear.
You probably did learn De Morgan's laws too, to be fair.
You are possibly right. But I really think the "or" form is genuinely easier to understand, even more so if you have less education in formal logic.

You might learn "x => y" in school (I didn't!) but if you did it was probably in the context of making implication (modus ponens). You are told p=>q, and then later you also find that p is true, so you can deduce that q is true. That's easy enough.

But figuring out whether p=>q is true is tricker (intuitively). Say someObj is falsey - is "someObj => someObj.data" true? Well, it is, because an implication p=>q is always true if p is not true e.g. "if normal dice rolls a 7 then the weather is rainy" is true because a normal dice never rolls a 7. Is that intuitively obvious for everyone? I can't believe it.

Is "!someObj || someObj.data" true if someObj is falsey? That is really easy in comparison - maybe not everyone will just see it at a glance, but you just check the two subexpressions one at a time, and immediately notice that "!someObj" is true. (What about if it's truethy? Also easy - the first subexpression is false, so you move on to the second one - it's only true if "someObj.data" is truethy.)

Why not:

assert(someObj && someObj.data);

Because that would be false if someObj is falsy. someObj => someObj.data, or !someObj || someObj.data (which are equivalent) would evaluate as true if someObj is falsy.
The point of implication is to say whether, in case P is true, that Q is true as well. If P is false, then the implication is always true.

So it’s !P || Q. Or P=>Q as the author proposes.

If(bValidate => IsValid()) { /* runs if either validation was unnecessary or passed */ }

And that would be equivalent to (!bValidate || IsValid()).

The proposal is for operator =>

I think it’s not an April Fool’s joke, but this looks awfully confusable with >=.

And confusable with lambda/function and pattern matching operators in other languages. Imagine only being an occasional C++ user, seeing =>, and thinking they added terse lambdas! You'd be in for a [big]<T>(){disappointment;}.
That's way too terse. You forgot 'mutable' and 'return' :(
Yeah, I'd lean towards a more obvious spelling, but most bikeshedding conversations bore me very quickly.

    !(a) || (b)
It’s a very obvious spelling :)
Pronounce it "or else", as in p or_else q. Hell, even re-using the else keyword mid-expression would work. Or you know, the ultimate in simplicity: don't implement this operator at all.

I agree with the other commenter that => would be better used for lambdas.

Are there any other programming languages that have this feature? I'm fairly certain Rust, Zig, C#, JavaScript, and Python do not.
It's not really correct to say that there are only 2 binary boolean operators, && and ||. There are also two really important ones, == and !=. They just so happen to not just be boolean operators and I guess they have slightly different behavior if your "booleans" can be more than 1 or 0.
There is also <, >, <=, and >=. Funnily, <= has the same truth table as the proposed => (as they mention in section 6.1)
They are interested in short-circuiting, so only &&, ||, and ? do that. They would want to avoid the evaluation of b() in a() => b() if a() is false.

But !a() || b() does that. So it seems that the proposal isn't needed. a implies b should just be written !a || b.

So many footguns in this proposal! From the misleadingly symmetric symbols <= => >=, to the unintuitive behavior (for non-mathematicians) in the case of negative left argument, to the similarity to operators in other languages. Short-circuiting is already possible with the well-understood (!A || B) notation, which has the added bonus of allowing (B || !A) as an alternative with the same truth table but opposite short-circuiting. This proposal saves one “!” character at a very high cost. Just… why?
I hope it doesn't get voted in,, it is not worth the added complexity.
Note that, AFAICT, this is in no way accepted into the standard. It's just a proposal (albeit by a distinguished graybeard).
Interestingly I find the examples very difficult to understand.

I replaced the table "raining? umbrella? faithful?" with "raining? umbrella? dry?".

Then made sense in my head only if I write something like this:

dry = umbrella || !raining

If I use my umbrella. I'm don't care it rains. Otherwise I will be dry only if it does not rain.

I prefer compiler intrinsics to look like functions, not operators.

For example, BMI1 ISA extension defines bitwise and not instruction, available in C++ as `_andn_u32()` or `_andn_u64()` intrinsics. That’s a rare operation most programmers are unfamiliar with, but it’s trivial to search internets for `_andn_u32`. It gonna be hard to find anything good searching for `=>`

I thought there were calls to simplify C++? This feels like the opposite direction. I've programmed in C++ for >20 years now and I can't think of a single moment where I would have wanted this feature.
Think about your own life. Does a toilet simplify your life? When you need to go to the bathroom, it seems much better to go to the toilet than say outside during the cold having to dig a hole in dirt every time and bury it. Yet toilets and plumbing add engineering and sophistication to your house.

This is the paradox. Simple languages push complexity to the user. Complex languages on the other hand simplify the user's tasks.

Has to be the right sort of complexity, though, or it makes the user's tasks worse over the long term. Every C++ project is already a dialect unto itself and this proposal would very much not help the situation.
I've been doing C++ since the 98 standard and C++ today is far easier, faster, more productive than anytime in the past. My code often feels as simple as python but much faster. Especially now that there are libraries using more modern standards.
I've only been doing C++ since the 2011 standard, but my sense of the language's evolution over time sort of matches yours. If you bother to learn the most complex, least-obvious, newest way to do something, the language has gotten safer, more functional, and more powerful.

You're way more productive using the container-agnostic `std::find()` than rolling your own version of it, as you might in other languages.

BUT I wouldn't say simpler. Do you slather `noexcept` on every method you write and turn every `const` to `constexpr`? :p Some advocate for that, and the have-a-new-keyword-for-something-that-should-actually-be-the-default-(but-of-course-the-defaults-will-never-not-be-backwards-here-because-we-got-them-wrong-way-back-and-too-much-existing-code-will-break-if-we-change-them) game is getting a little crazy for me.

"Complex languages on the other hand simplify the user's tasks."

You have an example? Cause I don't see how this is true.

Supporting generics from the get go instead of using code generation pre-processors.
> Simple languages push complexity to the user. Complex languages on the other hand simplify the user's tasks.

I don't think this captures the uniquely awful combination of "object oriented" + "low level (manual memory management)" that C++ chose. I think that's the most inherently complex dyad of traits you can choose for a programming language, and I think it's why C++ is the most complex programming language that's ever existed. They even tried hiding the complexity in shame with implicit behavior, like the compiler synthesizing the "rule of 5" functions for you, meaning you have to go out of your way and mark them as "deleted" to tell it not to do that when you know it'll do it wrong and leak memory and you have to memorize what the "rule of 5" is. (The only other language I can think of that went down the same route is D, but I don't know how complex it is in comparison to other languages. Maybe Walter Bright can argue it's a counterexample to my argument cause it's waaay simpler than C++. But then I'll counter-counter argue that it has garbage collection. But then again that's optional. My brain hurts.)

That is C++'s fame, and it is indeed quite complex.

However people that assert that, usually never went through PL/I, ALGOL 68, Ada, Common Lisp standards, nor have realized how JVM/Java, CLR/C#, Python/StdLib have changed during the circa 30 years of their existence.

This would be brilliant for helping simplify some contracts (preconditions, postconditions and invariants).
What captivated me was how good looking this PDF is lol!

I run `pdfinfo` and found out it was created with LaTeX...I need its settings so bad...I adore good looking, elegant PDF files!

Please don't! Save that syntax for lambdas instead. It's so much nicer to be able to say

  x => x + y
instead of

  [&](auto &&x) { return x + y; }
Because C++ goes through the effort of letting you manually specify capture lists, I suspect they would never introduce a syntax which did not
Why not just ((not p) or q), logically equivalent. ;D
What's with the coffee mug stains on the last page?
makes me think the whole thing is a joke...? because it's obvious this wasn't scanned.
It's just a funny thing LaTeX users sometimes add to their papers.
Insanity!

Programs must be maintained. This means that a programmer must be able to read a program and understand it. Forcing the programmer to understand implication makes no sense.

We do give up understandability already with templates. Templates can be a source of non-understanding, but also there is no replacement for templates. Implications don't need a new feature since ?: already solves this.

Compare this proposal to another weird C feature:

   char \*a;
   ...
   17[a] = 'b';
where, although the array operator is associative, it simply isn't used that way in code because it offers no useful feature. Therefore it is an insane feature which is harmless. The implication proposal is not harmless.