Colons and other annotative characters

# Waldemar Horwat (15 years ago)

On 11/22/10 10:13, Brendan Eich wrote:

 { foo : G : 33 }
  1. let typedObj = { foo : 33 } : { foo : G }; // a la ES4

  2. let typedObj = { foo :: G : 33 }; // the guards strawman

  3. let typedObj = { (foo : G) : 33 }; // the ML-ish way

  4. let typedObj = { foo @ G : 33 }; // funny cartoon chars

Good list. Out of those five, the only one I'd find compelling would be the first:

{ foo : G : 33 }

Alternatives 0, 1, and 3 have the problems that were already well-stated. 2 has strange placement of parentheses.

If we're brainstorming, I'd throw out an alternative for the object initializer syntax:

{name: value} // What we have now, for compatibility {name = value} // Identical behavior to {name: value} {name: type = value} // Adding a type annotation

If we're looking at other ASCII characters for type annotations, a few other characters such as the backtick might be an option:

{name`type: value} {name!type: value} {name%type: value} {name~type: value}

 Waldemar
# Mike Shaver (15 years ago)

I'd expect that

o = { a : b = 5 }

Was legal now, setting both o.a and b to 5. Not at a shell, is there an exception in the grammar for assignment expressions in the value position?

{ a = 5 : T } might work, though.

Mike On Nov 22, 2010 6:09 PM, "Waldemar Horwat" <waldemar at google.com> wrote:

On 11/22/10 10:13, Brendan Eich wrote:

{ foo : G : 33 }

  1. let typedObj = { foo : 33 } : { foo : G }; // a la ES4

  2. let typedObj = { foo :: G : 33 }; // the guards strawman

  3. let typedObj = { (foo : G) : 33 }; // the ML-ish way

  4. let typedObj = { foo @ G : 33 }; // funny cartoon chars

Good list. Out of those five, the only one I'd find compelling would be

the first:

{ foo : G : 33 }

Alternatives 0, 1, and 3 have the problems that were already well-stated.

2 has strange placement of parentheses.

If we're brainstorming, I'd throw out an alternative for the object

initializer syntax:

{name: value} // What we have now, for compatibility {name = value} // Identical behavior to {name: value} {name: type = value} // Adding a type annotation

If we're looking at other ASCII characters for type annotations, a few

other characters such as the backtick might be an option:

# Brendan Eich (15 years ago)

On Nov 22, 2010, at 3:08 PM, Waldemar Horwat wrote:

On 11/22/10 10:13, Brendan Eich wrote:

{ foo : G : 33 }
  1. let typedObj = { foo : 33 } : { foo : G }; // a la ES4

  2. let typedObj = { foo :: G : 33 }; // the guards strawman

  3. let typedObj = { (foo : G) : 33 }; // the ML-ish way

  4. let typedObj = { foo @ G : 33 }; // funny cartoon chars

Good list. Out of those five, the only one I'd find compelling would be the first:

{ foo : G : 33 }

Alternatives 0, 1, and 3 have the problems that were already well-stated. 2 has strange placement of parentheses.

Parens do hurt, I always thought so -- I find 2 the least evil of 0-3 though.

If we're brainstorming, I'd throw out an alternative for the object initializer syntax:

{name: value} // What we have now, for compatibility {name = value} // Identical behavior to {name: value} {name: type = value} // Adding a type annotation

Isn't the last ambiguous with legal JS today (well, with const, but that's not important AFAICT):

js> const T = {}

js> function f(x) { return {p: T = x}; }

js> o = f(42) ({p:42})

ES5 strict mode is the basis for Harmony, so the assignment would be an early error, but are guard bindings required to be const?

If we're looking at other ASCII characters for type annotations, a few other characters such as the backtick might be an option:

{name`type: value} {name!type: value} {name%type: value} {name~type: value}

Do you mean only for initialisers, or for all declarations. In a var x!T = v; example, he unary operator (! or ~) seems problematic here in light of ASI unless the production is restricted before the operator.

% as "mod" has some metaphorical appeal but really, these all seem like Perlish line noise compared to colon.

# Waldemar Horwat (15 years ago)

On 11/22/10 15:16, Brendan Eich wrote:

{name: type = value} // Adding a type annotation

Isn't the last ambiguous with legal JS today (well, with const, but that's not important AFAICT):

Yeah, you're right. This won't work.

 Waldemar
# Andreas Gal (15 years ago)

I think there is too much fear of changing the "semantics" of for-in. Its semantics is already rather fuzzy. Allowing meta-programmability of for-in (instead of creating a new for-:) syntax doesn't create any additional surprises or hazards for JS programmers.

  1. We have already agreed on an enumerate() hook which is triggered by traditional for-in. It returns a list of strings, but those are not necessarily keys.
  2. enumerate() can contain arbitrary JS code, so for-in can already trigger all sorts of random behavior, and people seem to be comfortable with it.
  3. iterate() is a natural extension of enumerate(). As enumerate(), it should be triggered by for-in. The only difference to the proxy enumerate trap is that iterate() doesn't eagerly force the creation of the list of values to be returned, which may not be possible for very large meta objects (databases, i.e.).

Its seems entirely random to cut off between 2) and 3). We are fine with enumerate(), but iterate() is somehow evil? The only see 2 semantic differences between the outcomes of enumerate() and iterate(). a) enumerate guarantees that all values are strings b) enumerate guarantees that all strings are unique

So it seems that some people feel that "unique strings" is an appropriate approximation for "keys".

There isn't much I can say about a). I think it would be more flexible and future-proof to allow non-string return values from iterators, but if we have to stringify non-string values returned from iterators, I could live with that.

As for b), the guarantees for it are already extremely weak. With proxies one can already today write code that breaks the uniqueness assumption of for-in.

function visit_keys(obj, f) { for (i in obj) f(i); }

visit_keys(obj, function(i) { delete obj.i; obj.i = 1; })

From my understand of the spec, a spec-conformant implementation is allowed to endless-loop on this code, continuously returning the same property name. So why do we cling to uniqueness where it doesn't exist in the first place?

Executive summary: iterate() is equivalent to enumerate(), both should work with for-in. We already agreed to accept enumerate, forcing iterate() into its own syntax is arbitrary. We can discuss sacrificing future-proofness and stringify return values of iterators, but rejecting iterators because they don't guarantee unique strings is bogus--that uniques doesn't exist elsewhere either.

# Brendan Eich (15 years ago)

On Nov 22, 2010, at 4:07 PM, Andreas Gal wrote:

Executive summary: iterate() is equivalent to enumerate(), both should work with for-in. We already agreed to accept enumerate, forcing iterate() into its own syntax is arbitrary. We can discuss sacrificing future-proofness and stringify return values of iterators

Stringify return values of iterators only when for-in is driving the iteration (I'm sure you meant ;-).

I somehow suspect stringifying the iterator next() return value from for-in machinery will not placate folks who want for-in not to be metaprogrammable. But harmony:proxies is already spec'ed with an enumerate trap. Something does not add up. You're right that the line between your items (2) and (3) is arbitrary.

BTW, I found a v8 implementation of proxies by Sam Shull, via TomVC's site:

brickysam26/node-proxy/tree/master/src

Thought I'd pass that on along to es-discuss to make up for the usual interminable iteration arguments :-P.

# David Herman (15 years ago)

I somehow suspect stringifying the iterator next() return value from for-in machinery will not placate folks who want for-in not to be metaprogrammable.

Nor would it work -- you wouldn't be able to get the values() or properties() iteration behavior, for example. It would be the worst of all possible compromises.

But harmony:proxies is already spec'ed with an enumerate trap. Something does not add up. You're right that the line between your items (2) and (3) is arbitrary.

Agreed.