Ternary Comparison Assignment Operators

Hi,

While building an app, I came across this code...

sortOrder = sortOrder === "asc" ? "desc" : "asc";

This is a bit repetitive and gets larger respective to the variable's name.

My idea is to have a kind of ternary assignment operator that looks something like this...

[variable] ?[comparison-operator] [expression1]: [expression2];

In action...

sortOrder ?=== "asc": "desc";

If sortOrder is asc this would make it desc, if it's not it would make it asc.

Variations

?=== // Ternary Strict Equality Assigner
?==  // Ternary Equality Assigner
?!== // Ternary Strict Inequality Assigner
?!=  // Ternary Inequality Assigner
?>   // Ternary Greater Than Assigner
?>=  // Ternary Greater Than or Equal To Assigner
?<   // Ternary Less Than Assigner
?<=  // Ternary Less Than or Equal To Assigner

Personally, I don't like this syntax so I'll look forward to your ideas :)

I think it's better to give this kind of operation a name:

const flipSortOrder = o => o === "asc" ? "desc" : "asc";

Because at some point, someone's gonna be surprised that "ASC" and "DESC" both become "asc", and you'll be happy there's a single place to make the test case-insensitive.

And then with pipeline operator...

sortOrder |>= flipSortOrder;
1 Like

A more general-purpose solution could be a self-assignment version of the pipeline operator ("|>="). From what I know, there aren't any plans to do that kind of thing, but I've heard people around express a desire for such an operator.

sortOrder |>= % === "asc" ? "desc" : "asc"
// same as
sortOrder = sortOrder |> % === "asc" ? "desc" : "asc"
// same as
sortOrder = (x => x === "asc" ? "desc" : "asc")(sortOrder)
2 Likes

Personally, I would solve this differently using a cyclic list sort of thing.

const sortOrders = ['asc', 'desc']
const currentSortOrder = 'asc'
const newSortOrder = cycleList(sortOrders, currentSortOrder)
// newSortOrder === 'desc'

This can also be used more generically with longer lists like ['asc', 'desc', 'custom'].

Also, a third optional object parameter could be introduced to cycle backwards or more than one step at a time.

const newSortOrder = cycleList(
  sortOrders,
  currentSortOrder,
  { direction: 'back', steps: 3 }
)

But I don't know if this would be better as a library. Maybe as part of the standard library proposal?

You should definitely keep the index instead of a literal for what you called a cycle list:

class CycleList {
	constructor(array) {
		this.array = array;
		this.value = 0;
	}
	get curr() {
		return this.array[this.value %% this.array.length];
	}
	get next() {
		return this.array[++this.value %% this.array.length];
	}
	get prev() {
		return this.array[--this.value %% this.array.length];
	}
	step(offset) {
		return this.array[(this.value += offset) %% this.array.length];
	}
	*[Symbol.iterator]() {
		while (true) {
			yield this.next;
		}
	}
}
const list = new CycleList(["ascending", "descending", "unspecified"]);
list.curr; // "ascending"
list.next; // "descending"
list.step(-2); // "unspecified"

Notice that it uses the proposed Modulo Operator %%.

Actually the point is, one (including myself) may not want to repeat the string literal especially when it’s very long; and there are risks of misspelling them (unless you use TypeScript):

sortOrder = sortOrder == "dictionarySortedInAscendingOrder" ? "dictionarySortedInDescendingOrder" : "dictionarySortedInAscendingOrder";

So, my advice is to keep a boolean instead of a string variable:

const orders = ["asc", "desc"];
let sortDesc = false;
// then
sortDesc = !sortDesc;
orders[+sortDesc]; // "desc"
// or in a single line:
orders[+(sortDesc = !sortDesc)];

@ethanlal04 @lightmare @graphemecluster @alinnert @theScottyJam
Hi all! Is it possible to do that? ternary Comparison Assignment Operators with Pipeline tap operator |: ?

case... my idea ... an idea:

const doTransfomration = data => data
  .filter(x => x != null)
  .tap(x => console.log(x))
  .sortOrder ?=== .map(x => x ** 2) or .filter(x => x > 100);

reference

@ethanlal04 @theScottyJam @lightmare @lightmare @graphemecluster @alinnert Hi all! Is it possible to do that? ternary Comparison Assignment Operators with Concurrent Async and Normal Await Evaluation Blocks.

case... my idea ... an idea:

async function sum(variable1, variable2) => {
  const a = async getA(variable1);
  const b = async getB(variable2);
  /* ... */
  return   ?=== a(variable1)+b(variable2)>10 or "false";
}

sum(2, 3);// 2+3=5 // false
sum(10, 10); // 10+10=20 // true

Notes

  1. I use the ternary symbol inside async/await
  2. If the sum is greater than 10 I return true, if less than 10 I return false

reference

An idea ... Ternary Comparison Assignment Operators with Negation opperator

case1.js

let value = 10

// check the condition
if (value >= 11) ? value++ : value--; // if pass... increment value++ // if fail ... decrement value

// program to check pass or fail
console.log(`You ${value} the exam.`);

case2.js

let value = 10

// check the condition
if (value >= 11) ? !false : value^^; // if pass... increment value++ // if fail ... decrement value

// program to check pass or fail
console.log(`You ${value} the exam.`);

Notes

  1. Only ideas