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

viable workaround before this lands? #12

Open
Pyrolistical opened this issue Mar 1, 2022 · 3 comments
Open

viable workaround before this lands? #12

Pyrolistical opened this issue Mar 1, 2022 · 3 comments

Comments

@Pyrolistical
Copy link

Pyrolistical commented Mar 1, 2022

if you want the first .next(0.1) to work with yield, you can just wrap the generator and just drop the first .next on the floor

const skipFirstYield =
  (generator) =>
  (...parameters) => {
    const iterator = generator(...parameters)
    iterator.next()
    return iterator
  }

const adder = skipFirstYield(function* (total = 0) {
  let increment = 1
  let request
  while (true) {
    switch ((request = yield (total += increment))) {
      case undefined:
        break
      case 'done':
        return total
      default:
        increment = Number(request)
    }
  }
})


let tally = adder()
tally.next(0.1) // argument will be used!
tally.next(0.1)
tally.next(0.1)
let last = tally.next('done')
console.log(last.value) // 1.3 as desired
@Pyrolistical
Copy link
Author

Pyrolistical commented Mar 1, 2022

Heck, would it be easier to spec function^ to skip the first yield instead of implementing function.sent?

then you would write

function^ adder(total = 0) {
  let increment = 1
  let request
  while (true) {
    switch ((request = yield (total += increment))) {
      case undefined:
        break
      case 'done':
        return total
      default:
        increment = Number(request)
    }
  }
}

@ljharb
Copy link
Member

ljharb commented Mar 1, 2022

In no way would adding a ninth kind of function be easier.

@hax
Copy link
Member

hax commented May 22, 2022

Dropping the first next is always a workaround, actually this is very close to what babel transformer do.

I don't like to add a new kind of function, but I agree we should explore alternative design, because the example codes for the use cases of this proposal always suffer some similar UX problems. Actually I tried some different alternative designs in last year, and it seem the best form is:

function *gen(...args) receive (x) { ... }

So @Pyrolistical 's code

function^ adder(total = 0) {
  let increment = 1
  let request
  while (true) {
    switch ((request = yield (total += increment))) {
      case undefined:
        break
      case 'done':
        return total
      default:
        increment = Number(request)
    }
  }
}

would become

function* adder(total = 0) receive (request) {
  let increment = 1
  while (true) {
    switch (request) {
      case undefined:
        break
      case 'done':
        return total
      default:
        increment = Number(request)
    }
    yield (total += increment)
  }
}

With some modification (drop weird "undefined" case), it could be simplified to:

function* adder(total = 0) receive (increment = 1) {
  while (true) {
    if (increment == 'done') return total
    total += Number(increment)
    yield total
  }
}

Concise and easy to understand ;-)

I would like to write more details about this alternative design in a separate issue soon.

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

3 participants