proposal-function.sent
proposal-function.sent copied to clipboard
viable workaround before this lands?
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
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)
}
}
}
In no way would adding a ninth kind of function be easier.
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.