dart-lang / language

Design of the Dart language
Other
2.65k stars 202 forks source link

literal-conforming assignment operator #3409

Open danielatk opened 10 months ago

danielatk commented 10 months ago

Let's say we're developing the system for a sneaky bank. In this bank, if the client's balance is 0, the system shows they have 100 to encourage them to take even more money. This function would like something like this:

int getBankBalance(String id) {
  int bankBalance = doSomeConsultation(id);
  if (bankBalance == 0) {
    return 100;
  }
  return bankBalance;
}

Alternatively one can use a ternary operator:

int getBankBalance(String id) {
  int bankBalance = doSomeConsultation(id);
  return (bankBalance == 0) ? 100 : bankBalance;
}

But there is no practical way of doing this with a one-liner. That's where the literal-conforming assignment operator would be useful. The proposed syntax is similar to the null-coalescing assignment operator:

int getBankBalance(String id) {
  return doSomeConsultation(id) ?== 0 => 100;
}

It would be an easy way of performing assignments when there are conditional requirements based on any literals, which goes beyond null safety.

Edit 1: after the suggestion made by @julemand101 the syntax was changed from a ?= b : c to a ?== b => c

julemand101 commented 10 months ago

Not sure if "one-liner" here means it is only allowed to be on one single line, of if we allow it to be a single expression. If the last, we can do the following with the new switch expression:

int getBankBalance(String id) => switch (doSomeConsultation(id)) {
      0 => 100,
      var bankBalance => bankBalance,
    };

For the suggested proposal, I feel the syntax is too close to the traditional ternary syntax which makes it rather hard to read.

It is also not clear if the goal is to support all operators of if we only add a specific syntax for the equal operation? Also, I think it is kinda confusing that ?= will trigger the == operator. So maybe, especially if further operators should be supported, the syntax should be ?==.

But that is just my own personal taste.

danielatk commented 10 months ago

@julemand101 the solution using the new switch syntax is very nice, indeed I need to retract my statement that it's not possible to perform with a one liner.

I also agree with your other two points, that maybe the ideal operator should be ?== and that the syntax is too similar to the ternary operator. For this second point maybe the use of => instead of : would be better suited.

lrhn commented 10 months ago

If we get case syntax into the conditional expression, it would be:

  (doSomeConsultation(id) case != 0 && var c) ? c : 100

Still needs to introduce a variable to carry the value out of the match again.

You can introduce an extension methods:

extension OrNull<T> on T {
  T? nullIf(T value) => this == value ? null : value;
  T try(T from, T to) => this == from ? to : value;
}

and do

doSomeConsultation(id).nullIf(0) ?? 100
// or
doSomeConsultation(id).tr(0, 100)

If it can be solved by a library function, it probably doesn't require special language syntax.