Live data from Hacker News

Safe Assignment

nalanj.dev

1–10 of 15 posts

Re: Safe Assignment

#2
It seems that the proposal itself has given up on the syntax in the article and will be proposing try expressions instead. The ?= syntax would never fly given that there's already a ??= operator that does something else.

Given that the (much simpler) throw expressions have been stuck in bureaucratic hell for 7 years, I look forward to seeing try expressions some time around the heat death of the universe.

Re: Safe Assignment

#3
Is try really meant for casual flow control, or should it be last ditch error recovery? ?: makes sense, forEach() makes sense, but not every kind of block needs a backup syntax.

Re: Safe Assignment

#4
The real safe assignment that I want to see is for optional chaining to be valid in LHS of assignments:

    foo?.bar = 42;
This would not perform the assignment if an optionally chained value was nullish. It downlevels to

    foo == null ? undefined : foo.bar = 42;
Given that the assignment is a SyntaxError now, this should be possible.

Re: Safe Assignment

#5
I don't think we'll ever see this. At least I hope we won't. Even specifying its behavior seems to be a nightmare. And you can basically just write it yourself.

    [val, err] ?= maybeThrow(); // instead of this
    [val, err] = wrapErr(maybeThrow); // you can write wrapErr yourself and use it forever
    [val, err] = wrapErr(maybeThrow, arg1, arg2); // you can even provide args

Re: Safe Assignment

#6

Is try really meant for casual flow control, or should it be last ditch error recovery? ?: makes sense, forEach() makes sense, but not every kind of block needs a backup syntax.

That will depend on language features (for example, multilevel/labelled `break`), performance (exceptions may or may not be slow or interfere with some kinds of optimizations), and personal preference (similar to the disagreement over whether or not it's bad practice to allow multiple `return` statements in one procedure).

Re: Safe Assignment

#7
Since the proposal is moving to try expressions, my main criticism there is that I don't usually just want the error as a value, as then I still need to check it and write a branch to handle the error case. It's nice that I could use const on the value variable instead of let, but that's such a small gain.

What I really want for the expression to return the value, but give a branch for the error case:

    // We still get a catch block to handle errors in
    const value = try foo() catch (e) {
      throw new MyError('Error trying to foo');
    };
Otherwise we have to write this to handle the error:

    const [value, error] = try foo();

    if (error) {
      throw new MyError('Error trying to foo');
    }
And it's far to easy to forget the error handling code altogether, resulting in silent failures.

edit: removed a brain-fart on a case that's already handled by JS :O

Re: Safe Assignment

#8

The real safe assignment that I want to see is for optional chaining to be valid in LHS of assignments: foo?.bar = 42; This would not perform the assignment if an optionally chained value was nullish. It downlevels to foo == null ? undefined : foo.bar = 42; Given that the assignment is a SyntaxError now, this should be possible.

You can avoid the SyntaxError by abusing boolean expressions a bit:

  > obj = {}
  {}
  > obj != null && (obj.bar = 42)
  42
  > obj
  { bar: 42 }
Not as pretty as your LHS case, but it works.

Re: Safe Assignment

#9
post #8

The real safe assignment that I want to see is for optional chaining to be valid in LHS of assignments: foo?.bar = 42; This would not perform the assignment if an optionally chained value was nullish. It downlevels to foo == null ? undefined : foo.bar = 42; Given that the assignment is a SyntaxError now, this should be possible.

You can avoid the SyntaxError by abusing boolean expressions a bit: > obj = {} {} > obj != null && (obj.bar = 42) 42 > obj { bar: 42 } Not as pretty as your LHS case, but it works.

With the length of that you might as well do:

    if (obj) obj.bar = 42

Re: Safe Assignment

#10
It's syntactic sugar for try/catch blocks. No new functionality.

Try/catch and exceptions seem to be tough for programmers to handle. You have to have disciplined unwinding for exception propagation to work well when an unwind goes through multiple calls.

Rust's rather simple "?" operator, which I once thought was underpowered, seems to be a workable solution. It's just syntactic sugar for return on error, but because there's a standard error trait, that usually works out well.

The lesson from this is to get your error objects right early in the history of a language, because you can't retrofit them. Once you have that right, how to report errors becomes sane, and the mechanism becomes less important.

Post reply on HN