tc39/proposal-function.sent

Suggestion: use `yield.sent` instead of `function.sent`

Opened this issue ยท 25 comments

It IMHO explains itself a little better, and it looks more generator specific than function.sent (which looks like it would belong in any function, not just any generator).

function.sent would also be helpful for arrow functions too, so it's not just generators - I think yield wouldn't be appropriate.

@ljharb What would function.sent be with arrows?

Hmm, maybe I'm thinking of something different. Rereading https://github.com/allenwb/ESideas/blob/master/Generator%20metaproperty.md does imply it's just for generators.

I was thinking of it like arguments for arrow functions.

A complication is that yield in non-strict code and outside of a generator yield is just a normal non-reserved identifier that can used as a variable name. Hence is such contexts yield.sent is just a property reference. We can't change that for backwards compat reasons. In a strict mode code (including within generator functions) yield.sent is a syntax error because yield is an AssignmentExpression rather than a PrimaryExpression.

It's bad enough that yield means different things based upon the context. I think it would be making things worse to for yield.sent to have differing valid context dependent meanings.

@allenwb Welp... ๐Ÿ˜ฆ Problem is, there's not really a lot of decent options...

Keep in mind, function.sent is generator-specific, so I was going from there, and my yield.sent was also meant to be generator-specific.

It's bad enough that yield means different things based upon the context. I think it would be making things worse to for yield.sent to have differing valid context dependent meanings.

Agreed, hence my reservations now. :-\

It's bad enough that yield means different things based upon the context. I think it would be making things worse to for yield.sent to have differing valid context dependent meanings.

If we take the point of view that non-strict mode is supposed to be mostly a backward-compatibility mode, and that new code are encouraged (and even forced in some cases) to be strict, that concern about non-strict mode should be less important.

I see a great opportunity to use yield.sent yield.last instead of function.sent.

We could imagine something more generic like this:

function * it() {
  let i = 0;
  while (true) {
    i += yield.last; // get absolute last value sent with next()
    yield i; // we don't update *i* here
  }
}

const _it = it();
_it.next(1); // 1
_it.next(2); // 3

Revisiting this, I feel yield.received would be better, since it's referring to the last received next parameter. yield.last, yield.sent, and function.sent all seem to imply the last yielded value, not the last received value.

hax commented

All names of yield.xxx suffer from the issues:

  1. yield.xxx and (yield).xxx have different semantics in generators.
  2. yield.xxx have different semantics in generators (meta property) and non-strict non-generator codes (normal property).
  3. yield.xxx and yield xxx looks close if the font of . is too inconspicuous ๐Ÿ˜‚
  4. yield.xxx and yield*xxx looks close if the font of . is too conspicuous ๐Ÿคฃ
  5. yield.xxx implies something caused by yield but actually the main reason of this proposal is about the first sent value before any yield (or without any yield).

I feel no any single issue is fatal, but there are too many potential ambiguity so maybe we should first consider alternatives of function.xxx instead of yield.xxx.

I don't think we have to worry about the font; anything can be unreadable with the wrong font.

Adding parens to things causes different semantics all over the place; i don't think that's a concern either - similarly, yield has a different semantic in generators vs non generators, so that's also not a concern.

However, your last point is compelling; it'd be great to find another alternative.

hax commented

Adding parens to things causes different semantics all over the place

@ljharb Could you explain more about that? I don't know other case which have different semantics between identifier.xxx with (identifier).xxx

it'd be great to find another alternative

Do you have any options? ๐Ÿ˜€

  • (a?.b).c vs a?.b.c
  • a, b.c vs (a, b).c
  • a + b + c vs (a + b) + c vs a + (b + c) when all three are different types
    etc

No suggestions yet.

hax commented

@ljharb What I mean is member access (or similar, like metaproperty) chaining ๐Ÿ˜…

  • a, b.c vs (a, b).c
  • a + b + c vs (a + b) + c vs a + (b + c)

So I don't think these two cases are comparable to yield.xxx vs (yield).xxx at all.

  • (a?.b).c vs a?.b.c

Actually this case seems weird at first glance, and there were several issues and discussions about that. IMO yield.xxx vs (yield).xxx is even worse because: it seems no real use case of (a?.b).c, but (yield).xxx in generator has valid use cases.

hax commented

I have some thought about the name.

The real meaning of function.sent in a generator function is "the value sent by the last next() call to a generator object which created by this generator function". The problem is, strictly speaking, the value is sent to "generator object" not "generator function", so function.sent sounds more like "a function instance sent to somewhere".

I feel if we use function.xxx it should sound like "the value that generator function got".

Here are the names go to my mind:

  • function.got
  • function.input
  • function.lastValue
  • function.currentValue
  • function.receivedValue
  • function.received
  • var.received (while var seems have no relationship with generator, it could be understand as a special variable in the generator function)

@hax What about function.received?

hax commented

@isiahmeadows Oh, I forgot to add it. Added now.

Currently I slightly prefer function.got or function.input because they are shorter ๐Ÿ˜›.

I also slightly worry about function.received could be considered to be a boolean.

What do you think of these names?

I remain concerned about using function for something that doesn't apply to all functions :-/

maybe function*.sent would work though (swap out "sent" for whatever the bikeshed produces)

hax commented

Though function*.sent may work, it looks very unlike a "meta property", not sure how committee would accept it ๐Ÿ˜… . And addition of * also make ergonomics a little bit worse (function is already long enough)

For me the best would be something able to retrieve every values sent though next (not only the first one)

keyWord may be any of: last, sent, received, input, ... => TO BE DEFINED

I agree with @ljharb , function.keyWord may be a little confusing. This specs only apply to generator functions intead of everyone.

(yield).keyWord => resolves first the yield, then go to the 'keyWord' property
yield.keyWord => returns the last value provided to next

I personally prefer yield.received as its for me the most explicit.

Note: function *f() { yield.received } throws an early error in Chrome, at least.

I do agree with @allenwb that yield.anything is not ideal, since it's a valid identifier anywhere else.

Note: function *f() { yield.received } throws an early error in Chrome, at least.

I do agree with @allenwb that yield.anything is not ideal, since it's a valid identifier anywhere else.

I'm not convinced that the fact yield is an identifier in sloppy mode is that compelling of a reason not to use it. It already has different meanings depending on context for tagged template literals (any others?) yield `foobar`;,

Although I do think the difference between (yield).blah vs yield.blah might be slightly confusing though given they can both occur in the same context. However I do feel like people wouldn't use (yield).prop as much with yield.blah.prop available anyway.

hax commented

I am considering maybe lastValue@yield could work ๐Ÿ˜‚ though it still not solve:

  • yield.xxx (or xxx@yield) implies something caused by yield but actually the main reason of this proposal is about the first sent value before any yield (or without any yield).

I strongly agree with yield.received

I strongly disagree with function.sent think something other would be better