Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscellaneous criticisms #32

Open
DavidJCobb opened this issue Aug 22, 2024 · 2 comments
Open

Miscellaneous criticisms #32

DavidJCobb opened this issue Aug 22, 2024 · 2 comments

Comments

@DavidJCobb
Copy link

DavidJCobb commented Aug 22, 2024

I'm writing this on too little sleep and with too little time, but my initial criticisms of this proposal are:


For example, when performing I/O operations or interacting with Promise-based APIs, errors can occur unexpectedly at runtime. Neglecting to handle these errors can lead to unintended behavior and potential security vulnerabilities.

Okay, but if we're gonna talk about safety, then you should probably do more to distinguish your proposal from Go (its apparent inspiration), a language that makes this issue a thousand times worse. In Go, all errors are received in a manner akin to your "safe assignment," and nothing forces you to ever actually handle an error (whether by doing something or deliberately discarding it). It's easy to just forget to handle an error, and if you do, then the failure becomes silent and the program continues running, potentially in an invalid state. By contrast, with exceptions and other thrown and caught errors, you either catch the error and deal with it, or have your program (or at least the current call stack) halt.

With your proposal, "safe assignment" is something you have to actively decide to do, and this is an advantage over Go: a "safe assignment" that does nothing with the error object is equivalent in behavior to an empty catch block, and almost as likely to be intentional. I think it's easier to forget error handling code after a "safe assignment" than it is to forget to write the body of a catch block, and I also think that the former mistake is harder to spot. An empty catch block looks distinctive and it looks wrong. You can tell at a glance that something's up. "Safe assignment" doesn't stand out so much; it looks, visually, like any other assignment operator, rather than forcing a change to the structure of the code with effects on indentation, scope, et cetera.

In fact, I'd say that calling this "safe assignment" isn't accurate. "Catching assignment" would be a better name in my opinion.

Using try/catch blocks has two main syntax problems:

The second code sample given here looks slightly worse than it needs to -- that is, it has a problem not related to the use of try/catch blocks alone. The json variable could be declared just before the try/catch block where the variable is needed, rather than at the very top of the function, miles away from where it's eventually used.

Move that variable declaration, and the resulting try/catch code is not significantly worse than any situation where the initialization of a variable relies on a nested scope (whether by necessity, or because a scope was introduced just to limit the lifetimes and relevance of some scratch variables), e.g.

function computeSomeData(foo) {
   let bar;
   {
      let list = frobulate(3);
      let dump = fiddle(list.length);
      bar = dump * magic(list);
   }

   let baz;
   {
      // ... etc. ...
   }

   return bar + baz;
}
@rafageist
Copy link

rafageist commented Aug 24, 2024

@DavidJCobb Great explanation!

In addition to that, I was just thinking about the mistake of calling it "safe assignment", because what the proposal really want is a "safe return" from a function. The assignment is done after obtaining the result of the function.

When we say A = B(), B() must first be executed, reaching some destination, and then the interpreter takes the value obtained and places it in A. The assignment is in fact always safe, what is not safe is the execution of the code and that is why it is encapsulated, until now in a try-catch, but the proposal wants to reduce it to an assignment operator to simplify a false problem.

In effect, this proposal is the solution to a false problem. A branch will always be needed, either with an if or a switch or something where you ask "if there was an error" and then act on path X or path Y.

The try-catch solves that.

@rafageist
Copy link

Finally, a response to Lea Verou:

"Exceptions are for exceptional cases. They disrupt the normal flow of a program, so try-catch helps the program recover from unexpected conditions. Before criticizing try-catch, consider if exceptions are used appropriately."

https://x.com/rafageist/status/1827205221988061207

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants