`of` operator ES7 proposal from Ian Bicking

# Brendan Eich (10 years ago)

From plus.google.com/+IanBicking/posts/PbXDtNF9Gg6:

Ian Bicking
Shared publicly - Mar 24, 2015

#Array

Huh, "for (attr in obj)" goes along with "if (attr in obj)", but "for (item of array)" doesn't have an equivalent "if (item of array)"

There is a proposal I guess for a method, but only for ES7: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

It's obvious in hindsight. Wants a @@hasInstance-like protocol, not just desugaring to includes with operands transposed to receiver and argument.

An of operator with unstratified symbol-named MOP hook helps various container-like objects cope with the vagaries of NaNs and indexOf / includes differences between arrays and strings, and (most winningly) lines up with for-of, as Ian points out, in a parallel to for-in and in.

I'm sure it's worth some debate, perhaps someone will k.o. the idea with an objection I can't think of, but I like it.

# Axel Rauschmayer (10 years ago)
  • Name-wise, is has a possibility? It feels more intuitive and I don’t think the duality with in matters (given that for-in will probably rarely be used in the future, due to for-of and Map).

  • Will it ever be possible to define arbitrary infix operators? If yes, should this operator wait until that feature is available?

# Michał Wadas (10 years ago)

First possible problem - "of" used in if statement can put iterator in unexpected state or result in arbitrary side effects. Of course, code like "piece.isKing()" can have side effects too, but any programmer comming from any language is conscious of this danger. Using operator obsfucates this.

# Brendan Eich (10 years ago)

Axel Rauschmayer wrote:

  • Name-wise, is has a possibility? It feels more intuitive and I don’t think the duality with in matters (given that for-in will probably rarely be used in the future, due to for-of and Map).

You don't want has for two reasons: it un-transposes operands back to receiver has value, which is almost as long as, and less worth a special form than, receiver.has(value) -- but that walks back into the has vs. include perplex.

Second reason: the parallel is in : for-in :: of : for-of. That's why the value goes on the left of the operator, the object (in method call terms, receiver) on the right.

  • Will it ever be possible to define arbitrary infix operators? If yes, should this operator wait until that feature is available?

Again we don't wait for macros before adding syntax. Takes too long, multiples risk, starves users of affordances.

People who know more about such things (dherman!) caution against ever getting sweet.js support into the browser-staged runtimes. It's an AOT tool.

# Brendan Eich (10 years ago)

Michał Wadas wrote:

First possible problem - "of" used in if statement can put iterator in unexpected state or result in arbitrary side effects.

What iterator?

First, you shouldn't assume this would be based on the Symbol.iterator protocol. I wrote something like @@hasInstance for instanceof was the precedent to follow.

Second, the iteration protocol would require exhaustively searching for values. Side effects of iteration are the least worry!

Finally, even if the iteration protocol were used, there would be no shared/reused iterator. You get a fresh one from well-implemented iterables.

# Frankie Bagnardi (10 years ago)

First, you shouldn’t assume this would be based on the Symbol.iterator protocol.

Would Object.create(null, {[Symbol.iterator]: value: ...}) work as it does in for..of?

It seems like the main problem would be infinite sequences. That means either infinite loops (ugh), or the language/user setting an arbitrary number of max values to check (ew).

If I do have an arbitrary iterable, I need to easily create something I can pass to for..of with if (x of fn(xs)) where fn is provided by ecmascript.

# Bergi (10 years ago)

Brendan Eich schrieb:

From plus.google.com/+IanBicking/posts/PbXDtNF9Gg6:

Huh, "for (attr in obj)" goes along with "if (attr in obj)", but "for (item of array)" doesn't have an equivalent "if (item of array)"

It's obvious in hindsight. An of operator …

I would like such an operator as well, but I can see a big problem with this proposal: "of" is not a reserved keyword. And it certainly has its usage as an identifier name already, most prominently: Array.of. The fantasyland applicatives do have such a method as well. I found a few uses of it in github code (most of those thousands are false positives or a particular test case, this example is not).

# Brendan Eich (10 years ago)

There's no problem making of contextual provided you use a restricted production:

RelationalExpression : RelationalExpression [no LineTerminator here] |of| ShiftExpression _

See harmony:egal#is_and_isnt_operators where we noticed that restricted productions allow the contextual use of new keyword-operators without breaking backward compatibility.

# Brendan Eich (10 years ago)

Frankie Bagnardi wrote:

Would Object.create(null, {[Symbol.iterator]: value: ...}) work as it does in for..of?

No, as with instanceof and @@hasInstance in general, you wouldn't get membership test for free.

But unlike instanceof, you wouldn't get common case behavior for free either, so that's the downside. You'd have to provide a value such as Array#includes for the property named by Symbol.hasElement (or whatever the best name analogous to @@hasInstance is).

It seems like the main problem would be infinite sequences. That means either infinite loops (ugh), or the language/user setting an arbitrary number of max values to check (ew).

Neither.

If I do have an arbitrary iterable, I need to easily create something I can pass to for..of with if (x of fn(xs)) where fn is provided by ecmascript.

You'd need to implement a separate MOP hook, let's call it @@hasElement for now.