arthurfiorette / proposal-safe-assignment-operator

Draft for ECMAScript Error Safe Assignment Operator
https://arthur.run/proposal-safe-assignment-operator/
MIT License
1.13k stars 12 forks source link

any idea to re-use the same error variable? #11

Open opensas opened 1 month ago

opensas commented 1 month ago

Prerequisites

Versions

n/a

A minimal reproducible example

n/a

Description

Can you think of some way to use the same error variable, something like this (I know it doesn't work like this, it's just an example)

async function getData() {
  const [err, response] ?= await fetch(
    "https://api.example.com/data"
  )

  if (err) {
    handleRequestError(err)
    return
  }

  const [err, json] ?= await response.json()

  if (err) {
    handleParseError(err)
    return
  }
  [...]
}

Steps to Reproduce

n/a

Expected Behavior

No response

JAForbes commented 1 month ago

@pygy taught me this, but JS already supports updating a previous destructured binding

let [a,b] = [1,2]

console.log(a,b)
// logs 1,2

void ([a,b] = [4,5])

console.log(a,b)
// logs 4,5

So you'd just do the same thing:

async function getData() {
  let [err, response] ?= await fetch(
    "https://api.example.com/data"
  )

  if (err) {
    handleRequestError(err)
    return
  }

  void ([err, json] ?= await response.json())

  if (err) {
    handleParseError(err)
    return
  }
  [...]
}
BThero commented 1 month ago

@JAForbes is it necessary to put ‘void (…)’ around the second assignment?

JAForbes commented 1 month ago

@BThero nope, if you use semi-colons carefully you can skip the parens and the void

let [a,b] = [1,2];

console.log(a,b);
// logs 1,2

[a,b] = [4,5];

console.log(a,b);
// logs 4,5

Just be careful, starting a new line with [...] without a semi colon on the previous expression will be treated as a property access, and starting a new line with (...) will be interpreted as a function call.

smeijer commented 1 month ago

Back to var 😅

async function getData() {
  var [err, response] ?= await fetch('https://api.example.com/data');
  if (err) return handleRequestError(err);

  var [err, json] ?= await response.json();
  if (err) return handleParseError(err);

  // ...
}
BThero commented 1 month ago

@JAForbes Ahh that's great. Yet another reason to enforce semicolons 😄

Thanks for the detailed explanation!

arthurfiorette commented 1 month ago

Maybe this is a valid reason to use the third approach try (as using), where the try operator would allow the overload of the error variable.

try [error, response] = await fetch('url')

if(err) { return 'error' }

try [error, json] = await response.json()
arthurfiorette commented 3 weeks ago

Reusing error variables is super confusing. I don't ever see this becoming a thing.

felippe-regazio commented 3 weeks ago

It doesn't fit all the scenarios, but you can use labeled statements in some cases:

fizz: {
  const [ error, result ] ?= fnA();
  ...
}

buzz: {
  const [ error, result ] ?= fnB();
  ...
}

But I can't see a practical reason for this since that we can just vary the variable name in the Iterable.

JAForbes commented 3 weeks ago

It doesn't fit all the scenarios, but you can use labeled statements in some cases:

fizz: {
  const [ error, result ] ?= fnA();
  ...
}

buzz: {
  const [ error, result ] ?= fnB();
  ...
}

But I can't see a practical reason for this since that we can just vary the variable name in the Iterable.

True, or even just unlabeled blocks:

{
  const [ error, result ] ?= fnA();
  ...
}

{
  const [ error, result ] ?= fnB();
  ...
}
khaosdoctor commented 3 weeks ago

It doesn't fit all the scenarios, but you can use labeled statements in some cases:

fizz: {
  const [ error, result ] ?= fnA();
  ...
}

buzz: {
  const [ error, result ] ?= fnB();
  ...
}

But I can't see a practical reason for this since that we can just vary the variable name in the Iterable.

True, or even just unlabeled blocks:

{
  const [ error, result ] ?= fnA();
  ...
}

{
  const [ error, result ] ?= fnB();
  ...
}

I would prefer to use try as using in this case over separated scopes, aesthetically speaking. But I think (and as it was stated on #4) this implies a different handling of the variable which could be a bigger scope, so I'd go with parallel assignments in this one