[HN Gopher] Safe Assignment
       ___________________________________________________________________
        
       Safe Assignment
        
       Author : commondream
       Score  : 14 points
       Date   : 2024-09-10 15:46 UTC (3 days ago)
        
 (HTM) web link (nalanj.dev)
 (TXT) w3m dump (nalanj.dev)
        
       | zarzavat wrote:
       | 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.
        
       | hyperhello wrote:
       | 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.
        
         | tbrownaw wrote:
         | 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).
        
       | spankalee wrote:
       | 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.
        
         | nuxi wrote:
         | 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.
        
           | Wingy wrote:
           | With the length of that you might as well do:
           | if (obj) obj.bar = 42
        
       | recursive wrote:
       | 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
        
       | spankalee wrote:
       | 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
        
       | Animats wrote:
       | 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.
        
       | timwis wrote:
       | Hah, thought this looked familiar... I had a similar idea back in
       | 2017 and published a little 5-line library to get this type of
       | syntax ([err, result] for async): https://github.com/timwis/eres
        
       ___________________________________________________________________
       (page generated 2024-09-13 23:01 UTC)