Negation opperator.

To increment/decrement a variable, there are shorthand operators for that:

let num = 0;

num++ // num += 1
console.log(num) // 1

num-- // num -= 1
console.log(num) // 0

If I wanted to negate a boolean, I would do it like this:

let bool = true;
bool = !bool;
console.log(bool) // false

I propose something easier:

let someReallyLongVariableThatIDontWantToWriteOutTwice = true;
someReallyLongVariableThatIDontWantToWriteOutTwice^^;

The ^^ operator will act identical to someVar = !someVar. Even if the variable is not a boolean, it will always turn into one. For example, by negating variable zero^^, it would turn turn a 0 into a true.

Examples:

bol0^^; // false  => true
bol1^^; // true   => false
num0^^; // 0      => true
num1^^; // 420.69 => false
str0^^; // ""     => true
str1^^; // "Hi!"  => false
nul0^^; // null  => true
nul1^^; // undefined => true
2 Likes

I've certainly felt the need for this kind of thing in the past.

I'll just note that when the pipeline proposal comes out, if they choose to also come out with a self-assignment version as a follow-on proposal, then the following would be possible, and would achieve the same result:

someReallyLongVariableThatIDontWantToWriteOutTwice |>= !^

It's certainly not as concise as "^^", but it does help out.

There's talk around about adding this "|>=" operator, but it's not going to be seriously considered until the pipeline operator goes through.

4 Likes

Ah, coincidentally, I just came across a scenario where I had to negate a deeply nested property while building an app w/ Svelte. I've also come across this many times in the past. I was on the brink of raising a discussion before you posted. So I'd give this a :+1: :)

Nitpick:

++num; // (num += 1)
num++; // ((num += 1) - 1)

^^someReallyLongVariableThatIDontWantToWriteOut___Once;

I've seen codebases that outright ban ++ and --. These operators can hurt readability for no good reason (especially postfix), and are basically unnecessary baggage everyone has to learn and teach, just because of C heritage.

So I wouldn't give unary logical negation much chance. Moreover, ^^ totally looks like logical XOR, which ­— ignoring the near-zero likelihood of that ever becoming a thing — would also give you negation in the form of flag ^^= true.

Aside from pipe-assignment, references could also solve this need — you'd use a ref-taking function negate(ref flag).

1 Like

The ^^ operator will act identical to someVar = !someVar. Even if the variable is not a boolean, it will always turn into one

I don't really understand why we need a new operator for non-boolean values when the current "!" operator works the same way for ANY type of expressions (not just for booleans):

!false; // false   => true
!true; // true     => false
!0; // 0           => true
!420.69; // 420.69 => false
!NaN; // NaN       => true
!""; // ""         => true
!"Hi!"; // "Hi!"   => false
!null; // null     => true
!undefined; // undefined => true

@MaxGraey, It's doesn't just coerce non-boolean values into boolean, it modifies the variable too. It is particularly useful when the variable name is either very long or deeply nested or both.

new operators, especially coupled ones, especially postfix ones, are a controversial stuff, even if it were a very useful operator. But as I understand it completely duplicates the prefix "!", only more convenient for long names? That is, instead of shortening the name and make it more concise, it is proposed to introduce a new operator completely repeating the existing functionality? Maybe I really don't understand the seriousness of the problem. Is there any other examples that show the importance and criticality of such an changes?

Perhaps you are a little confused. My proposal does not duplicate the prefix !. The operator ^^ will change the value of the variable, just like ++ and --.

someVar++; // someVar += 1
someVar--; // someVar -= 1
someVar^^; // someVar = !someVar

As demonstrated, when performing someVar^^, the variable is set to not-itself.

So this is not a duplicate of the prefix !. I hope this clears things up.

@lightmare - I agree that having both i++ and ++i is really confusing - I'm glad most newer languages don't include them. But, I don't really have a problem with having just ++i. (Like you said, i++ is especially confusing). However, the mere fact that both exist can make it more desirable to ban both altogether, because it's still easy to forget which way round the "++" needs to go (before? Or after the variable name?).

If, we only supplied a prefix "^^" operator, I would be ok with that. Though, I also do have concerns about the specific syntax choice, and I'm not sure there's really any great syntactic alternative, and the varName |>= !^ is good enough for my purposes.

1 Like

Now I see. Thanks for explanation.

1 Like

@theScottyJam @lightmare That's an interesting perspective. I've used a bunch of high-level languages (Java, Dart, and a few others), but of those, the only one that doesn't have increment/decrement is Python, but I always thought that was strange. I can see how newbies could get confused about prefixed vs suffixed incrementation. But if I'm being completely honest, these operators are so specific and have such a narrow function, I find it hard to believe that anyone who uses JS regularly (or even casually) will have a problem using them. I suppose if you are new and just learning JS, it could confuse a few learners, but even then, I'm sure that these operators would be the least of their confusion.


As for alternative syntax, I've considered a few other consecutive characters such as ~~, but this already parses as two bitwise-negations. I've also thought about =!, which would work like bool=!;, but then I thought about how it would work on the other side of the variable (=!bool; I don't think so).

I got the idea of ^^ from having used bool^=1 to swap a variable of 1 to 0 and vice-versa. This fits my needs, but then variable bool will always be a number, not a boolean. ^^ would negate a variable whilst keeping it of type "boolean".

1 Like

Huh, do you really find it that intuitive? I always have to pause and think for a while with these kinds of problems:

let i = 10
if (i++ >= 11) console.log('Does this log?')

I'd much prefer these kinds of shorthand tricks to be separated into their own line.

let i = 10
if (i >= 11) console.log('Does this log?')
i++

If JavaScript didn't have "++", you would almost be forced to write your code expanded out like that.

let i = 10
if (i >= 11) console.log('Does this log?')
i += 1

But, certainly not everyone feels this way, which is why these shorthand tricks happen.

Python's not the only language that doesn't have ++. Rust doesn't have it either. But yes, many of the C inspired languages do have it. These languages also tend to have lots of other C features that aren't necessarily the best idea, but in the interest of keeping the language familiar to new comers, such features were added anyways. And, maybe better, alternative ideas weren't floating around at the time.

1 Like

@lightmare - I don't think we'll ever get an xor operator (^^) - the truth table for xor would be exactly the same as the truth table for !== when using booleans as operands.

1 Like

would be sooo nice.
Finally I wouldn't have to do variable = variable === false when i want to invert a value in vanilla js
(i think this is already in TypeScript)

@theScottyJam @DiriectorDoc
Note that ^^ will be unavailable if the pipeline proposal comes out with the topic token being ^.
(%% should be for the modulo operator.)
Maybe we can use ~~ but allowing only postfix.

After all, I doubt that they are going to include the self-assignment pipeline operator in the current or any future proposal.

1 Like

I don't know. I haven't seen any committee members criticize this idea yet. In fact, it's been labeled as a good idea for a follow-on proposal (see here). But, we'll see what happens, I know the delegates have their hands pretty full, so it can sometimes take some time to get around to these follow-on proposals.