ES RegExp processor

2017-04-15 Thread Dmitry Soshnikov
(this is mostly an FYI post on JS regexes processing tool)

Recently I've been posting about ES RegExp parser[1], which eventually got
evolved into a generic ES RegExp processor (called `regexp-tree`). This can
be used for different kinds of purposes, and regarding ECMAScript spec --
it can be used to check/implement new proposals, new syntax, etc.

Currently the tool includes the following modules:

- Parser (including support for recent stage 3 proposals)
- Traversal
- Generic transformer
- Optimizer
- Compat-transpiler
- Interpreter (work in progress)

For example, the `optimizer`[2] module is capable of translating, and
fixing your regexes from:

```js
/[a-zA-Z_0-9][A-Z_\da-z]*\e{1,}/
```

To equivalent:

```js
/\w+e+/
```

There is also an ESLint plugin with auto-fixing exist for it.

And the `compat-transpiler`[3] can be used to run/translate named capturing
groups, "dotAll" flag, etc.

```js
/(?a)\k\1/
```

Translated into (with tracking group names for further runtime purposes):

```js
/(a)\1\1/
```

The `interpreter` module can be used to actually run new regexes, or check
semantics of the spec, when new features are added. This may follow at
implementation an actual ES spec (and other DFA/NFA engines can be built).
Note: there is also a way to run newer regexes using compat-transpiler.

Please feel free to reach me in case you have any questions, or would like
to add/implement any new feature in the tool.

Dmitry

[1] https://esdiscuss.org/topic/es-regexp-parser
[2] https://www.npmjs.com/package/regexp-tree#using-optimizer-api
[3] https://www.npmjs.com/package/regexp-tree#using-compat-transpiler-api
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-21 Thread Dmitry Soshnikov
On Tue, Mar 21, 2017 at 11:49 AM, Michael J. Ryan 
wrote:

> I slightly disagree... mainly in that as it stands, we have a fairly loose
> type coercion system that allows almost anything to be coerced into a
> boolean... in this case "parse" at least in my mind means that it should
> cover the most common use cases.   I understand that Boolean("false")
> doesn't currently work this way, and why Date.parse doesn't give a date
> instance is a bit beyond me.
>
> With my suggested polyfill your use case would work as expected...
> However, JS interacts with more than just serialized results from JS.  It
> interacts with input from multiple systems, sources, users and good/bad the
> content of users.  The type coercion as it exists for boolean is in order
> to provide for simplistic validation... why an empty string coerces false,
> for example.  Much like we have defined "falsey" values in JS, I think that
> Boolean.parse should have common truthy values/strings that can predictably
> be converted as a true, where all else is false.
>
> If all it does is:
>
> input => String(input).toLowerCase() === 'true';
>
> what is the point of extending Boolean?
>
>
Yeah, all good points, but they open a door for more questions mentioned
above (so many different formats, "yes", "1", "on", etc, and "why one, but
not another?", and "why not i18n?").

So to reduce this, having a good MVP would be good. Then, if there is a
need, it can be extended by adding.

The actual practical use-case I want to solve is:

- Not to use "raw building material" (aka "syntactic garbage") to solve the
issue. With this I mean using non-semantic techniques to achieve the goal,
like RegExp testings, JSON.parsing, etc. This is also a building material:
"String(input).toLowerCase() === 'true';", and users want nice semantic
library.

- To solve `Boolean('false')` issue. This is an actual use-case I had, when
was asked why Boolean type coercion treats "false" as true, and there is no
good answer other than -- "it's specified so". So to keep backward compats
we need Boolean.parse(...) for this.

So the only question it needs to address whether we accept truthy/false
values, or only strings.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-20 Thread Dmitry Soshnikov
On Mon, Mar 20, 2017 at 4:59 PM, Michael J. Ryan  wrote:

> My suggestion for a polyfill.
>
> if (!Boolean.parse) {
>   Boolean.parse = function(input) {
> // return false if it is already falsy
> if (!input) return false;
>
> var expr = String(input);
>
> // return false if it's reasonably too long of a string
> if (expr.length > 10) return false;
>
> // test trimmed input against truthy values
> return (/^(-?1|y|t|yes|true)$/).test(expr.trim().toLowerCase());
>   }
> }
>
> -1/1 are common database boolean/bit fields
> y/yes also common inputs for truthiness
> t/true also common for truthiness
>

Yeah, these might be good in general, although I'd like to reduce the
proposal to minimum vital version, and JS related. The problem we are
trying to solve is to parse `"false"` as `false`. It's not possible with
`Boolean('false')` today. And all the JSON.parse, and regexp manipulations
are too low-lever implementation details; users want good semantic library!
:)

So:

```
Boolean.parse('true'); // true
Boolean.parse('false'); // false
```

That's all we need for now, and already will be much better semantic
alternative too all existing "non-semantic building material".

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES RegExp parser

2017-03-20 Thread Dmitry Soshnikov
On Mon, Mar 20, 2017 at 9:19 AM, Dmitry Soshnikov <
dmitry.soshni...@gmail.com> wrote:

>
> On Mon, Mar 20, 2017 at 8:36 AM Jason Orendorff <jason.orendo...@gmail.com>
> wrote:
>
>> The second approach, hands down.
>>
>> 1. With the first approach, you're setting up a situation where it's very
>> easy to write buggy analysis code: if you forget to check `re.quantifier`
>> anywhere, your code will run, but you have a bug. Much easier to only have
>> to check `re.type`.
>>
>> 2. If you have a regexp `re` and you want to programmatically build a
>> regexp that matches one or more repetitions of it, it's much easier to
>> write `{type: '+', expression: re}` than to have to examine `re.quantifier`
>> and (if it's already present) figure out how to modify it.
>>
>> 3. With the first approach, you don't have to represent `(?:)` group in
>> the AST at all (rather like how Esprima drops redundant parentheses). With
>> the latter, I think you have to, because it's possible for a single regexp
>> "node" to have multiple quantifiers: `/(?:\d{4,6})?/`
>>
>> To me this is not even a question.
>>
>
> Jason, thanks; all good points! And I came to similar conclusions while
> was experimenting. Wanted to double-check, thanks for confirming.
>
>
OK, I added docs and specs for AST node types, which can also be a good
learning material:
https://www.npmjs.com/package/regexp-tree#ast-nodes-specification

Any feedback is welcome!

Parsing regexes is fun :) with this you realize that these are completely
valid regexp patterns:

```
/$$$/.test(''); // true

/$^/.test(''); // true

/[---]/.test('-'); // true, a range from '-' to '-'!
/[-]/.test('-'); // true
```

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-20 Thread Dmitry Soshnikov
On Mon, Mar 20, 2017 at 12:12 PM, Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> As mentioned in the gist, and FWIW, -1 here.
>
> `/^true$/i.test(str)` works since ever for the specified use case
>
> `Boolean.parseBoolean(1)` that returns `false` is a footgun.
>
> Either we talk about a better definition of truthy-like values, or having
> a public spec about just string type and `true` as value looks like the
> solution for 1% of use cases that's also already covered by `JSON.parse`
>
>>
>>
Still, semantics matter :) With a `JSON.parse` you may parse any JSON
value, and then will have to do extra checks. RegExp test is also less
semantic. Initially in the thread I considered truthy/falsey values, but
then reduced to strings only, and took Java's implementation, but this can
be discussed. The need for a semantic method from `Boolean` still exists,
instead of using ad-hoc technics like JSON or regexp, which are just
implementation details for the semantic method.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-20 Thread Dmitry Soshnikov
On Mon, Mar 20, 2017 at 12:09 PM, kdex  wrote:

> One could argue that `parse` makes more sense, as there is really just
> that one way to parse a bool.
>
>
I agree, just `parse` sounds good (similar to `Date.parse`, and
`JSON.parse`). Since in `parseInt`, the `Int` is a quantifier.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-20 Thread Dmitry Soshnikov
On Mon, Mar 20, 2017 at 11:57 AM, T.J. Crowder <
tj.crow...@farsightsoftware.com> wrote:

> Any reason for not just using `Boolean.parse`? (Rather than repeating
> `Boolean` in the function name?)
>
>>
>>
Just a copy-paste from Java, similarly was done with `parseInt` taken from
Java. But just `parse` probably would work too. For consistency and
predictability `parseBoolean` is probably better now.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-20 Thread Dmitry Soshnikov
On Thu, Mar 16, 2017 at 1:55 PM, Dmitry Soshnikov <
dmitry.soshni...@gmail.com> wrote:

> Similar to `Number.parseInt`, the `Boolean.parseBooelan` might be useful
> for "boolean strings" retrieved from some string-based storages, which do
> not support other types at serialization.
>
> ```
> Boolean.parseBoolean('true'); // true
> Boolean.parseBoolean('false'); // false
> ```
>
>
OK, here the actual proposed spec for it:
https://gist.github.com/DmitrySoshnikov/5ee1a7d51d8dbe159ae917876b27f36a

I made it plain simple (anything which is not case-insensitive `"true"` is
`false`), and copy-pasted from Java.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES RegExp parser

2017-03-20 Thread Dmitry Soshnikov
On Mon, Mar 20, 2017 at 8:36 AM Jason Orendorff 
wrote:

> The second approach, hands down.
>
> 1. With the first approach, you're setting up a situation where it's very
> easy to write buggy analysis code: if you forget to check `re.quantifier`
> anywhere, your code will run, but you have a bug. Much easier to only have
> to check `re.type`.
>
> 2. If you have a regexp `re` and you want to programmatically build a
> regexp that matches one or more repetitions of it, it's much easier to
> write `{type: '+', expression: re}` than to have to examine `re.quantifier`
> and (if it's already present) figure out how to modify it.
>
> 3. With the first approach, you don't have to represent `(?:)` group in
> the AST at all (rather like how Esprima drops redundant parentheses). With
> the latter, I think you have to, because it's possible for a single regexp
> "node" to have multiple quantifiers: `/(?:\d{4,6})?/`
>
> To me this is not even a question.
>

Jason, thanks; all good points! And I came to similar conclusions while was
experimenting. Wanted to double-check, thanks for confirming.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-18 Thread Dmitry Soshnikov
On Fri, Mar 17, 2017 at 7:42 AM Augusto Moura 
wrote:

> What would be the result for `Boolean.parseBoolean('undefined')` and
> `Boolean.parseBoolean('null')`?
>

Perhaps this should be restricted to JSON-compatible "false" only. Other
possible may include "", and "0". For stricter handling "null",
"undefined", and similar strings may even throw as non-Boolean parseable.

Dmitry

>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-16 Thread Dmitry Soshnikov
On Thu, Mar 16, 2017 at 7:04 PM, Karl Cheng  wrote:

> On 17 March 2017 at 08:03, Ben Newman  wrote:
> > Just to check my understanding, would
> >
> >   Boolean.parseBoolean = function (value) {
> > return !! (value && JSON.parse(String(value)));
> >   };
> >
> > be a reasonable polyfill for your proposed function?
>
> Not quite -- that would throw for strings that are not valid JSON, e.g.:
>
> ```
> Boolean.parseBoolean('{dd]');
> ```
>
> It'd probably be more like:
>
> ```
> Boolean.parseBoolean = function (val) {
>   if (val === 'false') return false;
>   return !!val;
> };
> ```
>

Looks good either (probably worth making case-insensitive).

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Boolean.parseBoolean

2017-03-16 Thread Dmitry Soshnikov
On Thu, Mar 16, 2017 at 2:03 PM, Ben Newman 
wrote:

> Just to check my understanding, would
>
>   Boolean.parseBoolean = function (value) {
> return !! (value && JSON.parse(String(value)));
>   };
>
> be a reasonable polyfill for your proposed function?
>
>
Yep, this looks good.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Proposal: Boolean.parseBoolean

2017-03-16 Thread Dmitry Soshnikov
Similar to `Number.parseInt`, the `Boolean.parseBooelan` might be useful
for "boolean strings" retrieved from some string-based storages, which do
not support other types at serialization.

```
Boolean.parseBoolean('true'); // true
Boolean.parseBoolean('false'); // false
```

This is to contrast current:

```
Boolean('false'); // true
```

In JS people do today:

```
let shouldRefresh = (data.shouldRefresh === 'true');
```

Other parsing results:

```
Boolean.parseBoolean('1'); // true
Boolean.parseBoolean(1); // true
Boolean.parseBoolean(); // true
Boolean.parseBoolean(true); // true

// Falsey:
Boolean.parseBoolean('0'); // false
Boolean.parseBoolean(''); // false
Boolean.parseBoolean(false); // false
```

The API, and the results are from Java's corresponding
`Boolean.parseBoolean` method:
https://docs.oracle.com/javase/7/docs/api/java/lang/Boolean.html#parseBoolean(java.lang.String)
.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-02-14 Thread Dmitry Soshnikov
On Mon, Jan 23, 2017 at 10:46 PM, Dmitry Soshnikov <
dmitry.soshni...@gmail.com> wrote:

>
> On Mon, Jan 23, 2017 at 5:24 PM, Waldemar Horwat <walde...@google.com>
> wrote:
>
>> On 01/11/2017 10:28, Michael Dyck wrote:
>>
>>> In the past, it has been said (usually by Brendan Eich) that TC39
>>> intends that the ECMAScript grammar be LR(1). Is that still the case? (I'm
>>> not so much asking about the "1", but more about the "LR".)
>>>
>>> If so, I'm wondering how lookahead-restrictions (e.g., [lookahead >> terminals]) fit into the LR approach. It seems like there are three
>>> possibilities:
>>>   - modify the grammar (before the parser is constructed),
>>>   - modify the construction of the parser, and/or
>>>   - modify the operation of the parser.
>>> It's not clear to me that any of these (or any combination of these)
>>> will work.
>>>
>>> Has anyone algorithmically generated an LR parser from the spec grammar?
>>> If so, how did you you handle lookahead-restrictions?
>>>
>>
>> I'm the source of the LR(1) condition.  I've been doing that ever since
>> ECMAScript Edition 3, and in fact am using the LR parser to help design and
>> debug the spec.  I have an implementation of the parser with a few
>> extensions to the LR grammar, including support for parametrized
>> productions, lookahead restrictions, and lexer-parser feedback used to
>> disambiguate things such as what token / will start.  I validate various
>> things such as making sure that there is no place where both an identifier
>> and a regular expression can occur.
>>
>>
> Thanks for the confirmation.
>
> > lookahead restrictions
>
> Yeah, all the lookahead restrictions, such as `lookahead ∉ {{, function}`
> add a lot of extra "No" productions, which makes the grammar
> (and hence the parsing table) bigger unfortunately. Example is e.g.
> `ExpressionNoIn`, `VariableDeclarationNoIn` from the spec, and similar for
> `...NoLeftCurrly`, and `...NoFunction` to support those lookahead
> restrictions, and allow `ExpressionStatement` to be parsed without
> "reduce/reduce" conflicts.
>
> That's why in the mentioned "sub-set" of the ECMAScript example language
> [1] I chose not to use the same syntax for function expression and function
> declaration: `fn foo() {}` for declaration, and just an arrow function for
> function-expressions :) -- no ambiguity, no lookahead restrictions, hence
> no larger grammar, hence a faster parser.
>
>  > lexer-parser feedback
>
> Yes, having a lexer/parser state solves it more elegantly.
>


FYI: I just built this as a proof of concept for ECMAScript's `{` and `}`,
and have parsed normally `{ }` in statement position as a `BlockStatement`,
and in the expression position as an `ObjectLiteral`. With special
"activation productions" one can change the lexer state, and yield
different token types for the same characters.

See the example here:
https://github.com/DmitrySoshnikov/syntax/blob/master/examples/parser-lexer-communication.g

And some details in the docs:
https://github.com/DmitrySoshnikov/syntax#access-tokenizer-from-parser-semantic-actions

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-02-03 Thread Dmitry Soshnikov
On Fri, Feb 3, 2017 at 2:32 PM, Waldemar Horwat <walde...@google.com> wrote:

> On 02/02/2017 15:56, Dmitry Soshnikov wrote:
>
>> On Thu, Feb 2, 2017 at 3:23 PM, Waldemar Horwat <walde...@google.com
>> <mailto:walde...@google.com>> wrote:
>>
>> On 02/01/2017 10:25, Dmitry Soshnikov wrote:
>>
>> As mentioned, Cover grammar is usually the process of the grammar
>> design itself (as in ES6 spec itself). I'm not aware of automatic
>> transformations for this (if you find any please let me know).
>>
>>
>> Cover grammars are an ugly hack that we had to add when there was no
>> other practical choice.  Avoid them as much as possible.  They are only
>> used in situations where lookahead restrictions and parametrized grammar
>> rules do not work in any practical way.
>>
>>
>> Yeah, absolutely agreed. The reason why I used cover grammar in that
>> example to parse `{` as a `Block` vs. `ObjectLiteral`, and handle
>> `ExpressionStatement` is to make the resulting grammar short, and don't
>> introduce a bunch of `NoCurly`, etc extra productions for this. That's also
>> said, this ugly hack also forces you to do post-processing overhead --
>> either validation of the nodes, or even re-interpretation (rewriting) to
>> other nodes -- in my case I have to actually check that all nodes between
>> `{` and `}` are properties, or vice-versa, statements, based on the
>> expression/statement position.
>>
>
> Don't use a cover grammar to unify blocks with object literals.  That's a
> really bad idea and you'll likely get it wrong.  If the `{` starts a block,
> then if the next token is a keyword such as `if` then it's parsed as a
> keyword.  If the `{` starts an object literal, then if the next token is a
> keyword then it's parsed as an identifiername.  As we extend the language,
> the expansions of these can later diverge to the point where you won't know
> whether a `/` starts a regular expression or is a division symbol.
>
>
Ah, good catch. In fact, this can be fixed by allowing keywords as property
names, as in JS (and in fact, I have just fixed it after your comment --
see example code changes in this commit:
https://github.com/DmitrySoshnikov/syntax/commit/ccb3029cf7515bc078436c37831e027b50cb7fa4
-- there are no ambiguities, and it's still correctly parsed as an
`ObjectLiteral`, or `Block` in needed position).

Just to note, this example language is a smaller sub-set of ECMAScript
grammar, but not ES grammar itself, so, so far, Cover grammar works ;)
(still being a "dirty hack" since the language syntax was designed so,
allowing the same construct in different logically positions).

P.S.:

Another observation to note, using Cover grammar for this specific case
with `{` requires parsing at least in LALR(1) mode, and SLR(1) will not
work, eventually reaching to "reduce-reduce" conflict for when parsing e.g.
an empty block inside the empty `{ { } }`:

(output from the parsing states analysis tool)

```
- BlockStatement -> BlockOrObject • (kernel, reduce by production 13)
- ObjectLiteral -> BlockOrObject • (kernel, reduce by production 68)
```

LALR(1) uses parametrized lookahead set, and is free from this issue. It's
the one which is used the most on practice anyways (taking more time for
table calculation though)

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-02-02 Thread Dmitry Soshnikov
On Thu, Feb 2, 2017 at 3:56 PM, Dmitry Soshnikov <dmitry.soshni...@gmail.com
> wrote:

> On Thu, Feb 2, 2017 at 3:23 PM, Waldemar Horwat <walde...@google.com>
> wrote:
>
>> On 02/01/2017 10:25, Dmitry Soshnikov wrote:
>>
>>> As mentioned, Cover grammar is usually the process of the grammar design
>>> itself (as in ES6 spec itself). I'm not aware of automatic transformations
>>> for this (if you find any please let me know).
>>>
>>
>> Cover grammars are an ugly hack that we had to add when there was no
>> other practical choice.  Avoid them as much as possible.  They are only
>> used in situations where lookahead restrictions and parametrized grammar
>> rules do not work in any practical way.
>>
>>
> Yeah, absolutely agreed. The reason why I used cover grammar in that
> example to parse `{` as a `Block` vs. `ObjectLiteral`, and handle
> `ExpressionStatement` is to make the resulting grammar short, and don't
> introduce a bunch of `NoCurly`, etc extra productions for this. That's also
> said, this ugly hack also forces you to do post-processing overhead --
> either validation of the nodes, or even re-interpretation (rewriting) to
> other nodes -- in my case I have to actually check that all nodes between
> `{` and `}` are properties, or vice-versa, statements, based on the
> expression/statement position.
>
> Practically, a cover grammar still can be slower because of such
> post-processing overhead (imaging you have a giant file with just object --
> all those now are needed to be validated to contain property nodes). OTOH,
> a trade off with lookahead restrictions is introducing ~1.5x more parsing
> states.
>
>
>> When designing the grammar, the preferences are:
>>
>> - Use standard LR(1) productions
>> - Use parametrized productions
>> - Use lookahead restrictions if parametrized productions would introduce
>> too many parameters into rules
>> - Use a cover grammar if the grammar can't be reasonably expressed in any
>> other way.  They're a last resort with lots of problems.
>>
>>
> Just to double-check, by "parametrized productions" you mean the
> `No` extra productions?
>
>

Or you actually mean "lookahead-parametrized" productions (like in SLR(1)
which doesn't use it, vs. LALR(1), or CLR(1) which do use it)?

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-02-02 Thread Dmitry Soshnikov
On Thu, Feb 2, 2017 at 3:23 PM, Waldemar Horwat <walde...@google.com> wrote:

> On 02/01/2017 10:25, Dmitry Soshnikov wrote:
>
>> As mentioned, Cover grammar is usually the process of the grammar design
>> itself (as in ES6 spec itself). I'm not aware of automatic transformations
>> for this (if you find any please let me know).
>>
>
> Cover grammars are an ugly hack that we had to add when there was no other
> practical choice.  Avoid them as much as possible.  They are only used in
> situations where lookahead restrictions and parametrized grammar rules do
> not work in any practical way.
>
>
Yeah, absolutely agreed. The reason why I used cover grammar in that
example to parse `{` as a `Block` vs. `ObjectLiteral`, and handle
`ExpressionStatement` is to make the resulting grammar short, and don't
introduce a bunch of `NoCurly`, etc extra productions for this. That's also
said, this ugly hack also forces you to do post-processing overhead --
either validation of the nodes, or even re-interpretation (rewriting) to
other nodes -- in my case I have to actually check that all nodes between
`{` and `}` are properties, or vice-versa, statements, based on the
expression/statement position.

Practically, a cover grammar still can be slower because of such
post-processing overhead (imaging you have a giant file with just object --
all those now are needed to be validated to contain property nodes). OTOH,
a trade off with lookahead restrictions is introducing ~1.5x more parsing
states.


> When designing the grammar, the preferences are:
>
> - Use standard LR(1) productions
> - Use parametrized productions
> - Use lookahead restrictions if parametrized productions would introduce
> too many parameters into rules
> - Use a cover grammar if the grammar can't be reasonably expressed in any
> other way.  They're a last resort with lots of problems.
>
>
Just to double-check, by "parametrized productions" you mean the
`No` extra productions?


> Lookahead restrictions fit very well into an LR(1) engine as long as
> they're limited to only one token, and that's what I've implemented in the
> validator.  You need to be very careful with them if looking more than one
> token ahead because lexing of the tokens can vary based on context.  For
> example, if the next few characters in front of the cursor are )/abc/i+,
> then what is the second token?  What is the third token?  It's actually
> context-dependent.
>
> The same problem is even worse for cover grammars.
>
>
Yeah, that's also true. Thanks again for the confirmation, that such a
validator even exists, it's good -- at least we know it's parsable in
principle. Those, that's said, on real practice now implementing a manual
recursive descent for ECMAScript is more approachable now.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-02-01 Thread Dmitry Soshnikov
On Wed, Feb 1, 2017 at 7:37 AM, Michael Dyck <jmd...@ibiblio.org> wrote:

> On 17-01-31 02:17 PM, Dmitry Soshnikov wrote:
>
>> The spec is a formal language definition (including for syntactic
>> grammar).
>>
>
> (Well, the extent to which the spec is formal is debatable. The grammar is
> the most formal part of it, but that's true of most programming language
> definitions.)
>
> It doesn't talk about specifics of implementation much, nor it's supposed
>> to
>> do so (so demanding this from spec isn't appropriate).
>>
>
> Right (and I'm pretty sure I didn't make such a demand).
>
> It doesn't tell one to implement an LR(1),
>>
>
> Nor should it.
>
> neither it describes the
>> techniques *how* one going to do so (even though as was confirmed in this
>> thread it's LR(1)-parsable). It just uses some formal notation for this,
>> e.g. `lookahead ∉ {{, function}`. Specific techniques *how exactly* you
>> going to achieve this, is not the purpose of the specification.
>>
>
> Right.



OK, I mostly meant that a spec can be fully abstract, even in abstract
definitions themselves, and use different notations instead of providing
fully "CFG-equivalence for lookahead restrictions".


>
>
> (but it's possible to clarify such techniques on discussions which we have
>> now -- please note though, the techniques described above are not an
>> "assumption", or a "guess", they are actual techniques used on practice to
>> achieve this in LR(1)).
>>
>
> I'm not disputing the actualness of the techniques. I'm saying:
>
>  - technique #1 (duplicated productions): As stated, looks insufficient
> for the ES grammar. Which may just mean that there's a more complicated
> version of the approach that *is* sufficient for ES.
>


Here's an example:
https://raw.githubusercontent.com/zaach/jison/master/examples/jscore.jison
(see how lookahead restriction for `{` in `ExpressionStatement` is
implemented using `NoBF` productions).



>
>  - technique #2 (cover grammar): Can you algorithmically (a) construct the
> cover grammar and (b) recover the parse according to the original grammar?
>

And this approach I chose (instead of duplicating productions) to handle
the same `{` lookahead restriction, what this comment explains:
https://github.com/DmitrySoshnikov/syntax/blob/master/examples/lang.bnf#L206-L222

As mentioned, Cover grammar is usually the process of the grammar design
itself (as in ES6 spec itself). I'm not aware of automatic transformations
for this (if you find any please let me know).



>
>  - technique #3 (parse-time actions): In the LR automaton, can you
> algorithmically distinguish action-avoided conflicts from 'true' conflicts?
>
>
> The spec in definitions is not consistent though. In one place it uses
>> explicit *technique* for lookahead restriction via the "No"
>> productions. In some cases it just uses formal description as  `lookahead
>> ∉
>> {{, function}`, leaving a specific technique to achieve this up to
>> implementations.
>>
>> In fact (for consistency), the rule from ES5:
>>
>> ```
>> for ( ExpressionNoIn ; Expression ; Expression ) Statement
>> ```
>>
>> could be described as:
>>
>> ```
>> for ( `lookahead ∉ {in}` Expression ; Expression ; Expression ) Statement
>> ```
>>
>> and would mean the same.
>>
>
> No, they wouldn't. ExpressionNoIn (or Expression[~In]) is a version of
> Expression that doesn't ("openly") use the 'in' operator (at the
> RelationalExpression level), i.e. it doesn't have the 'in' operator
> somewhere in the *middle*, whereas
>[lookahead ∉ {in}] Expression
> prohibits an Expression that *starts* with the token 'in'. You can't
> express the 'NoIn' restriction with any finite amount of lookahead, because
> a RelationalExpression can be arbitrarily large.
>
>
I agree, the example not the best, I was leaning to, that a spec could use
even more abstract definition for this instead of explicit productions.



>
> You may search for ES5 LR(1) construction (there are several over
>> internets), they use the described above techniques for `lookahead ∉ {{,
>> function}` (adding `NoCurlyBrace`, or `NoFunction` productions).
>>
>
> But the chances are low that they've been algorithmically generated from
> the ES spec. And while it's conceivable I could figure out how to do it
> algorithmically by examining examples of it done manually, I'm doubtful of
> that too.
>
>
I'm not sure about "algorithmic" transformations, but yeah, how the grammar
is described in the spec, and which extra transformation you have to do in
the r

Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-31 Thread Dmitry Soshnikov
The spec is a formal language definition (including for syntactic grammar).
It doesn't talk about specifics of implementation much, nor it's supposed
to do so (so demanding this from spec isn't appropriate).

It doesn't tell one to implement an LR(1), neither it describes the
techniques *how* one going to do so (even though as was confirmed in this
thread it's LR(1)-parsable). It just uses some formal notation for this,
e.g. `lookahead ∉ {{, function}`. Specific techniques *how exactly* you
going to achieve this, is not the purpose of the specification.

(but it's possible to clarify such techniques on discussions which we have
now -- please note though, the techniques described above are not an
"assumption", or a "guess", they are actual techniques used on practice to
achieve this in LR(1)).

The spec in definitions is not consistent though. In one place it uses
explicit *technique* for lookahead restriction via the "No"
productions. In some cases it just uses formal description as  `lookahead ∉
{{, function}`, leaving a specific technique to achieve this up to
implementations.

In fact (for consistency), the rule from ES5:

```
for ( ExpressionNoIn ; Expression ; Expression ) Statement
```

could be described as:

```
for ( `lookahead ∉ {in}` Expression ; Expression ; Expression ) Statement
```

and would mean the same.

You may search for ES5 LR(1) construction (there are several over
internets), they use the described above techniques for `lookahead ∉ {{,
function}` (adding `NoCurlyBrace`, or `NoFunction` productions). That's
also said, it could be rewritten using Cover grammar which adds though
post-processing overhead -- that might be the reason why some of the
`No` productions were removed from ES6 spec, but `lookahead ∉
{{, function}` is still there. More complex cases like Arrow functions
params is still implemented as a Cover grammar.

Dmitry


On Tue, Jan 31, 2017 at 7:56 AM, Michael Dyck <jmd...@ibiblio.org> wrote:

> On 17-01-30 06:20 PM, Dmitry Soshnikov wrote:
>
>> On Mon, Jan 30, 2017 at 2:22 PM, Michael Dyck <jmd...@ibiblio.org
>> <mailto:jmd...@ibiblio.org>> wrote:
>>
>>
>> 1. Using "No" productions.
>>
>> The problem with this approach is that, in general, a
>> lookahead-restriction is not a restriction on the nonterminal
>> that
>> immediately follows it in the production, it's a restriction
>> on
>> the next few input elements, which might be generated by more
>> than just that nonterminal.
>>
>> Well, in this case it's not a "lookahead" anymore.
>>
>> It isn't a "lookahead" in the resulting grammar, but it is in the
>> original, and the two grammars should define the same language. What
>> I'm
>> saying is that it's incorrect to assume that the effect of the
>> lookahead
>> (in the original) can be confined to the nonterminal that immediately
>> follows, which is what the suggested transformation does.
>>
>>
>> A "lookahead" is a terminal token. A non-terminal is not a "lookahead".
>>
>
> Okay, so then in my previous statement, read "lookahead" as
> "lookahead-restriction". (But I did say "lookahead-restriction" in the
> statement before that.)
>
>
> To reiterate, imaging you have:
>>
>> ```
>> • (x, y)
>> ```
>>
>> and
>>
>> ```
>> • (x, y) -> { return x + y; }
>> ```
>>
>> where `•` is a cursor position. Your lookaheads are "(", "x", "," "y",
>> etc.
>> Usually 1 lookahead token is enough to route the parser, in this case "(".
>>
>> What you're talking that you need not these lookaheads (at the beginning
>> of
>> the cursor), but *after* the parsed non-terminal (i.e. after fully parsed
>> `(x, y)`), i.e. you're looking for "->", which goes at the end of the
>> non-terminal.
>>
>
> I'm not saying I don't need the lookahead tokens right after the cursor.
> But I am saying that the lookahead tokens that the hypothetical parser
> needs to examine (in order to enforce a lookahead-restriction), even if
> it's only 1 or 2, might extend past the 'next' nonterminal.
>
> But that's an awkward way to express my objection.
>
> To recap, I'm talking about the suggestion to replace:
> [lookahead != ] Nonterminal
> in a production in the original grammar with
> Nonterminal-that-does-not-start-with-that-sequence
> (and a bunch of new productions) in the transformed grammar, and whether
> that's a valid transformation.
>
> I'm saying it isn'

Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-30 Thread Dmitry Soshnikov
On Mon, Jan 30, 2017 at 2:22 PM, Michael Dyck <jmd...@ibiblio.org> wrote:

> On 17-01-30 03:00 PM, Dmitry Soshnikov wrote:
>
>>
>> On Mon, Jan 30, 2017 at 9:26 AM, Michael Dyck <jmd...@ibiblio.org
>> <mailto:jmd...@ibiblio.org>> wrote:
>>
>> On 17-01-30 12:15 AM, Dmitry Soshnikov wrote:
>>
>>
>> As mentioned above, there are two ways to handle lookahead
>> restrictions in
>> LR-parser:
>>
>> 1. Using "No" productions.
>>
>> So, e.g., one could take the production
>> IterationStatement : ...  [lookahead != 'let'] LHSExpr ...
>> and transform it into
>> IterationStatement : ... LHSExpr-that-does-not-start-with-let ...
>> and then generate productions for the new nonterminal, e.g.
>> LHSExpr-that-does-not-start-with-let :
>> New-Expression-that-does-not-start-with-let
>> Call-Expression-that-does-not-start-with-let
>> etc, (eventually bottoming out when a RHS of the original grammar will
>> either always or never start with 'let').
>>
>> Correct, and this is how ES spec itself handles all those "No"
>> duplicated productions.
>>
>
> If you're talking about the 'NoIn' productions in ES5, that seems only
> marginally relevant, since they don't address a lookahead problem (i.e., a
> problem that could have been solved via a lookahead-restriction).
>
> The problem with this approach is that, in general, a
>> lookahead-restriction is not a restriction on the nonterminal that
>> immediately follows it in the production, it's a restriction on the
>> next
>> few input elements, which might be generated by more than just that
>> nonterminal.
>>
>>
>> Well, in this case it's not a "lookahead" anymore.
>>
>
> It isn't a "lookahead" in the resulting grammar, but it is in the
> original, and the two grammars should define the same language. What I'm
> saying is that it's incorrect to assume that the effect of the lookahead
> (in the original) can be confined to the nonterminal that immediately
> follows, which is what the suggested transformation does.


A "lookahead" is a terminal token. A non-terminal is not a "lookahead".

To reiterate, imaging you have:

```
• (x, y)
```

and

```
• (x, y) -> { return x + y; }
```

where `•` is a cursor position. Your lookaheads are "(", "x", "," "y", etc.
Usually 1 lookahead token is enough to route the parser, in this case "(".

What you're talking that you need not these lookaheads (at the beginning of
the cursor), but *after* the parsed non-terminal (i.e. after fully parsed
`(x, y)`), i.e. you're looking for "->", which goes at the end of the
non-terminal. This is not possible, since it's not a lookahead at that
specific cursor position. It will be a lookahead after you have parsed the
non-terminal corresponding to "(x, y)".

So you can't have two non-terminals for this, since it'll be a
"reduce/reduce" conflict, and you need a cover grammar here.



>
>
> You could have k=2,3,...N for lookahead in parser generators, but it's
>> not like parse the whole non-terminal, and then see a lookahead after it.
>> This "parse whole non-terminal till the end" might be parse the whole
>> program.
>>
>
> I don't really follow what you're suggesting there.


Like mentioned above:

```
• (x, y) -> { return x + y; }
```

In order to determine whether it's a grouping operator, or arrow function
params, it's not enough analyzing a "lookahead" being that the cursor
position. You need to actually fully parse this non-terminal, and advance
to this position:

```
(x, y) • -> { return x + y; }
```

and from there you may already analyze a real lookahead. However, the
problem is the "(x, y)" might the full program (imagine million of entries
on several GBs file source code -- what kind of "lookahead" can you analyze
here? :))



>
>
>
> In this case a cover grammar is simpler, and that's why it's used
>> starting since ES6 spec.
>>
>
> But note that none of the ES5 lookahead-restrictions was replaced with a
> cover grammar in ES6. They're all still lookahead-restrictions.


Sure, because it's normally possible to do with the "No" doubled
productions. So this actually answers your initial question (it's a real
practice).


>
>
>
>> I'm not saying this is insurmountable, but it does seem to get messy
>> fairly quickly.
>>
>> And it's unclear how this approach would handle a
>> lookahead-re

Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-30 Thread Dmitry Soshnikov
On Mon, Jan 30, 2017 at 9:26 AM, Michael Dyck <jmd...@ibiblio.org> wrote:

> On 17-01-30 12:15 AM, Dmitry Soshnikov wrote:
>
>>
>> As mentioned above, there are two ways to handle lookahead restrictions in
>> LR-parser:
>>
>> 1. Using "No" productions. This unfortunately may double number
>> of productions in some sub-grammar. E.g. to handle Block vs. ObjectLiteral
>> in ECMAScript, one needs to double all the expression productions to
>> correctly parse `ExpressionStatement`. As an example in the spec itself,
>> take a look e.g. at `RelationalExpression` and `RelationalExpressionNoIn`,
>> and how it repeats (doubles) all the productions but with "NoIn" suffix
>> https://es5.github.io/#x11.8
>>
>
> So, e.g., one could take the production
> IterationStatement : ...  [lookahead != 'let'] LHSExpr ...
> and transform it into
> IterationStatement : ... LHSExpr-that-does-not-start-with-let ...
> and then generate productions for the new nonterminal, e.g.
> LHSExpr-that-does-not-start-with-let :
> New-Expression-that-does-not-start-with-let
> Call-Expression-that-does-not-start-with-let
> etc, (eventually bottoming out when a RHS of the original grammar will
> either always or never start with 'let').
>
>

Correct, and this is how ES spec itself handles all those "No"
duplicated productions.



> The problem with this approach is that, in general, a
> lookahead-restriction is not a restriction on the nonterminal that
> immediately follows it in the production, it's a restriction on the next
> few input elements, which might be generated by more than just that
> nonterminal.


Well, in this case it's not a "lookahead" anymore. You could have
k=2,3,...N for lookahead in parser generators, but it's not like parse the
whole non-terminal, and then see a lookahead after it. This "parse whole
non-terminal till the end" might be parse the whole program. In this case a
cover grammar is simpler, and that's why it's used starting since ES6 spec.
Take a look e.g. at `CoverParenthesizedExpressionAndArrowParameterList`
from ES2015.

A simplified example:
https://github.com/DmitrySoshnikov/syntax/blob/master/examples/lang.bnf#L514-L524

By just looking at:

```
(x, y)
```

you can't tell whether it's a grouping operator (`SequenceExpression`
node), or a beginning of a lambda function (i.e. its parameters node). So
in the generic `ParenthisizedExpression` production, you reinterpret it
either to lambda parameters, or keep just a grouping operator, if there is
no `LambdaTail`. Here it's a function of course, though for this you have
to parse `(x, y)` not as `LambdaParameters`, and not as
`SequenceExpression`, but as a generic `ParenthisizedExpression`, and using
Cover grammar:

```
(x, y) -> { return x + y; }
```



> I'm not saying this is insurmountable, but it does seem to get messy
> fairly quickly.
>
> And it's unclear how this approach would handle a lookahead-restriction at
> the end of a production.


Yes, it adds a bunch of duplicated productions to the grammar, which on
practice may increases number of parsing states simnifically. As a real
practical example: ES5 spec in LALR(1) mode would increase from ~350 states
to 470.


>
>
>
> 2. Another approach is to use Cover grammar.
>>
>
> Is there a way to automatically (a) construct the cover grammar and (b)
> reconstruct the parse tree as if parsed by the original grammar, or do you
> code it manually?
>
>
Usually it's a manual process of designing a grammar, and defining
post-processing static semantics. Take a look again in the example language
I gave above, it have couple of case of cover grammar.


>
> P.S.: there is actually option #3 -- to use "S-attributed" parser actions,
>> it's when you may execute handling action not only at the end of
>> production
>> (i.e. not only on "reduce"), but after each element on RHS:
>>
>
> I'm doubtful this would help. I wouldn't expect the LR-parser-generator to
> 'understand' the content of actions, so it can't use them to alter the
> generation of the parser, and so the LR automaton will have lots of
> conflicts (because it can't 'separate' the alternatives that the
> lookahead-restrictions are there to separate).
>
>
Oh, it'll work for sure, depending on how powerful a parser generator is.
Yes, technically it'll be a "reduce-reduce" conflict in the table, but
parser will never enter this state based on the semantic action executed
*before* entering some non-terminal (not after). In this "before" action
you can communicated to lexer, and check the lookahead.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-29 Thread Dmitry Soshnikov
On Tue, Jan 24, 2017 at 8:23 AM, Michael Dyck  wrote:

> On 17-01-23 08:24 PM, Waldemar Horwat wrote:
>
>> On 01/11/2017 10:28, Michael Dyck wrote:
>>
>>>
>>> If so, I'm wondering how lookahead-restrictions (e.g., [lookahead >> terminals]) fit into the LR approach. It seems like there are three
>>> possibilities:
>>>   - modify the grammar (before the parser is constructed),
>>>   - modify the construction of the parser, and/or
>>>   - modify the operation of the parser.
>>> It's not clear to me that any of these (or any combination of these) will
>>> work.
>>>
>>> Has anyone algorithmically generated an LR parser from the spec grammar?
>>> If so, how did you you handle lookahead-restrictions?
>>>
>>
>> I have an implementation of the parser with a few extensions to the LR
>> grammar, including support for ... lookahead  restrictions, ...
>>
>
> Great! So how do you handle lookahead restrictions?
>
>
As mentioned above, there are two ways to handle lookahead restrictions in
LR-parser:

1. Using "No" productions. This unfortunately may double number
of productions in some sub-grammar. E.g. to handle Block vs. ObjectLiteral
in ECMAScript, one needs to double all the expression productions to
correctly parse `ExpressionStatement`. As an example in the spec itself,
take a look e.g. at `RelationalExpression` and `RelationalExpressionNoIn`,
and how it repeats (doubles) all the productions but with "NoIn" suffix
https://es5.github.io/#x11.8

2. Another approach is to use Cover grammar. It's when you parse a node
with two possible ways, and enforce (reinterpret) needed sub-nodes in the
cover-grammar post-processor (after having parsed a generic node). E.g. I
chose this approach to parse generically `ObjectLiteral`, and `Block` to
handle `{` lookahead restriction for `ExpressionStatement`. This approach
allows not to double grammar (hence making parsing table smaller), however
adds some post-processing overhead.
https://github.com/DmitrySoshnikov/syntax/blob/master/examples/lang.bnf#L206-L222

P.S.: there is actually option #3 -- to use "S-attributed" parser actions,
it's when you may execute handling action not only at the end of production
(i.e. not only on "reduce"), but after each element on RHS:

```
statement
options
{
k = 1 ;
}
: { input.LA(1) == LBRACE }? block
| statementTail
;
statementTail
: variableStatement
| emptyStatement
| expressionStatement
...
```

This option is probably the best alternative.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-11 Thread Dmitry Soshnikov
The "early errors" are just parser errors which are enforced not by grammar
rules, but by additional validation algorithms which follow the parsed
node. E.g. `eval` cannot be assigned in strict mode: it's not a grammar
issue (grammar allows `eval` on LHS), and it's not a runtime issue, it's an
"early error" enforced by static semantics, which still issues it as a
`ParseError`. Example in handling it in a semantic action for a production
(on a simplified `AssignmentExpression`):

```
%%

AssignmentExpression
  : IDENTIFIER '=' Expression {
  const id = $1;

  // Static semantics: early parser error:

  if (mode.isStrict && (id === 'eval' || id == 'arguments')) {
throw new ParseError(
  '`eval` and `arguments` cannot be assigned in strict mode.'
);
  }

  return {
type: 'AssigmentExpression',
left: $1,
right: $3,
  };
}
```

Similarly other "early errors".

BTW, here is the example I mentioned above of how Flow has to do
backtracking in parsing in some edge cases, making the grammar completely
not LR(1) anymore:
https://github.com/babel/babel/issues/1991#issuecomment-121708242

Dmitry


On Wed, Jan 11, 2017 at 7:13 PM, Isiah Meadows <isiahmead...@gmail.com>
wrote:

> Okay. I see now. How do early errors factor into this?
>
> On Wed, Jan 11, 2017, 21:49 Dmitry Soshnikov <dmitry.soshni...@gmail.com>
> wrote:
>
>> Well, it's still context-free (contex-sensitive may have terminals on LHS
>> too, JS cannot). It requires extra cover grammar, and additional static
>> semantics, but still potentially can be parsed by a LALR/CLR parser - yes,
>> you'll have to do parsed nodes reinterpretation in semantics handlers (e.g.
>> validate and transform parsed ObjectLiteral into an ObjectPattern when
>> parsing destructuring), but should be doable in general. It won't be doable
>> if lookaheafs won't be enough, and only a backtracking can recover (like
>> the cases with Flow parser).
>>
>> Dmitry
>>
>>
>> On Wed, Jan 11, 2017 at 6:09 PM Isiah Meadows <isiahmead...@gmail.com>
>> wrote:
>>
>> Heuristically, I doubt it's even context-free at this point, considering
>> the concept and widespread prevalence of early errors now. I suspect it's
>> mildly context-sensitive (maybe tree-adjoining?), but I'm no formal
>> language expert here.
>>
>>
>>
>> On Wed, Jan 11, 2017, 14:23 Dmitry Soshnikov <dmitry.soshni...@gmail.com>
>> wrote:
>>
>> One yet has to check the pure ES6+ grammar to be LR(1) compatible (the
>> Cover grammar with nodes reinterpretations makes it harder), but for a very
>> practical use-case, e.g. combined with Flow, it'll not be easy to have an
>> automated parser (since Flow's parser uses backtracking for some edge cases
>> which is already not LR-parser).
>>
>> I have some subset of ES6 working as an example language for Syntax
>> tool[1] (since I just took a bunch of productions from JS), but I haven't
>> tried the full ES6 grammar (not having time to work on this project, since
>> it'll be not a straightforward process of just matching the grammar 1:1 to
>> the parser generator -- based on the above reasons).
>>
>> Long time ago I also had a brief discussion with authors of another
>> popular parser generators for JS. Both didn't try it as well, but mentioned
>> that even for ES5 it was hard to parse e.g. regexp, etc.
>>
>> Someone (with enough time for the project) should just sit, and spend
>> some time actually porting the grammar from the spec on some powerful
>> parsers generator.
>>
>> [1] Syntax: https://github.com/DmitrySoshnikov/syntax
>> [2] https://twitter.com/DmitrySoshnikov/status/666327209959751680
>>
>> On Wed, Jan 11, 2017 at 10:28 AM, Michael Dyck <jmd...@ibiblio.org>
>> wrote:
>>
>> In the past, it has been said (usually by Brendan Eich) that TC39 intends
>> that the ECMAScript grammar be LR(1). Is that still the case? (I'm not so
>> much asking about the "1", but more about the "LR".)
>>
>>
>>
>>
>>
>> If so, I'm wondering how lookahead-restrictions (e.g., [lookahead > terminals]) fit into the LR approach. It seems like there are three
>> possibilities:
>>
>>
>>   - modify the grammar (before the parser is constructed),
>>
>>
>>   - modify the construction of the parser, and/or
>>
>>
>>   - modify the operation of the parser.
>>
>>
>> It's not clear to me that any of these (or any combination of these) will
>> work.
>>
>>
>>
>>
>>
>> Has a

Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-11 Thread Dmitry Soshnikov
Well, it's still context-free (contex-sensitive may have terminals on LHS
too, JS cannot). It requires extra cover grammar, and additional static
semantics, but still potentially can be parsed by a LALR/CLR parser - yes,
you'll have to do parsed nodes reinterpretation in semantics handlers (e.g.
validate and transform parsed ObjectLiteral into an ObjectPattern when
parsing destructuring), but should be doable in general. It won't be doable
if lookaheafs won't be enough, and only a backtracking can recover (like
the cases with Flow parser).

Dmitry


On Wed, Jan 11, 2017 at 6:09 PM Isiah Meadows <isiahmead...@gmail.com>
wrote:

> Heuristically, I doubt it's even context-free at this point, considering
> the concept and widespread prevalence of early errors now. I suspect it's
> mildly context-sensitive (maybe tree-adjoining?), but I'm no formal
> language expert here.
>
>
>
> On Wed, Jan 11, 2017, 14:23 Dmitry Soshnikov <dmitry.soshni...@gmail.com>
> wrote:
>
> One yet has to check the pure ES6+ grammar to be LR(1) compatible (the
> Cover grammar with nodes reinterpretations makes it harder), but for a very
> practical use-case, e.g. combined with Flow, it'll not be easy to have an
> automated parser (since Flow's parser uses backtracking for some edge cases
> which is already not LR-parser).
>
> I have some subset of ES6 working as an example language for Syntax
> tool[1] (since I just took a bunch of productions from JS), but I haven't
> tried the full ES6 grammar (not having time to work on this project, since
> it'll be not a straightforward process of just matching the grammar 1:1 to
> the parser generator -- based on the above reasons).
>
> Long time ago I also had a brief discussion with authors of another
> popular parser generators for JS. Both didn't try it as well, but mentioned
> that even for ES5 it was hard to parse e.g. regexp, etc.
>
> Someone (with enough time for the project) should just sit, and spend some
> time actually porting the grammar from the spec on some powerful parsers
> generator.
>
> [1] Syntax: https://github.com/DmitrySoshnikov/syntax
> [2] https://twitter.com/DmitrySoshnikov/status/666327209959751680
>
> On Wed, Jan 11, 2017 at 10:28 AM, Michael Dyck <jmd...@ibiblio.org> wrote:
>
> In the past, it has been said (usually by Brendan Eich) that TC39 intends
> that the ECMAScript grammar be LR(1). Is that still the case? (I'm not so
> much asking about the "1", but more about the "LR".)
>
>
>
>
>
> If so, I'm wondering how lookahead-restrictions (e.g., [lookahead  terminals]) fit into the LR approach. It seems like there are three
> possibilities:
>
>
>   - modify the grammar (before the parser is constructed),
>
>
>   - modify the construction of the parser, and/or
>
>
>   - modify the operation of the parser.
>
>
> It's not clear to me that any of these (or any combination of these) will
> work.
>
>
>
>
>
> Has anyone algorithmically generated an LR parser from the spec grammar?
> If so, how did you you handle lookahead-restrictions?
>
>
>
>
>
> -Michael
>
>
> ___
>
>
> es-discuss mailing list
>
>
> es-discuss@mozilla.org
>
>
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
>
>
> ___
>
>
> es-discuss mailing list
>
>
> es-discuss@mozilla.org
>
>
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: LR(1) grammar/parser and lookahead-restrictions

2017-01-11 Thread Dmitry Soshnikov
One yet has to check the pure ES6+ grammar to be LR(1) compatible (the
Cover grammar with nodes reinterpretations makes it harder), but for a very
practical use-case, e.g. combined with Flow, it'll not be easy to have an
automated parser (since Flow's parser uses backtracking for some edge cases
which is already not LR-parser).

I have some subset of ES6 working as an example language for Syntax tool[1]
(since I just took a bunch of productions from JS), but I haven't tried the
full ES6 grammar (not having time to work on this project, since it'll be
not a straightforward process of just matching the grammar 1:1 to the
parser generator -- based on the above reasons).

Long time ago I also had a brief discussion with authors of another popular
parser generators for JS. Both didn't try it as well, but mentioned that
even for ES5 it was hard to parse e.g. regexp, etc.

Someone (with enough time for the project) should just sit, and spend some
time actually porting the grammar from the spec on some powerful parsers
generator.

[1] Syntax: https://github.com/DmitrySoshnikov/syntax
[2] https://twitter.com/DmitrySoshnikov/status/666327209959751680

On Wed, Jan 11, 2017 at 10:28 AM, Michael Dyck  wrote:

> In the past, it has been said (usually by Brendan Eich) that TC39 intends
> that the ECMAScript grammar be LR(1). Is that still the case? (I'm not so
> much asking about the "1", but more about the "LR".)
>
> If so, I'm wondering how lookahead-restrictions (e.g., [lookahead  terminals]) fit into the LR approach. It seems like there are three
> possibilities:
>   - modify the grammar (before the parser is constructed),
>   - modify the construction of the parser, and/or
>   - modify the operation of the parser.
> It's not clear to me that any of these (or any combination of these) will
> work.
>
> Has anyone algorithmically generated an LR parser from the spec grammar?
> If so, how did you you handle lookahead-restrictions?
>
> -Michael
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Iterator combinator methods

2016-12-09 Thread Dmitry Soshnikov
There are some good examples with `MapIterator`, and its `filter`, `map`,
`collect` or `collectAs` final methods here (from some old discussion):
https://github.com/rwaldron/tc39-notes/blob/master/es6/2014-11/nov-19.md#58-mapprototypemap-and-mapprototypefilter-spec--set
I'm pretty sure there should've been other discussions on this, but I'm not
sure about current state.

Just build a working prototype library from those examples as a proof on
concept. Then spec'ing it should be relatively easy after it (assuming a
champion who will be willing to run it through).

Dmitry

On Fri, Dec 9, 2016 at 7:46 AM, Benjamin Gruenbaum 
wrote:

> Hey,
>
> I remember a lot of talk about adding `.map/.filter` etc to iterators. The
> benefits of doing this are pretty big and I think fairly well understood
> and several other proposals (like observables and async iterators) would
> benefit from it.
>
> (I expand on the big advantages this has over Array#map/filter if needed).
>
> Is anyone currently working on such a proposal? Was it discussed?
>
> I'd really like to see it move forward.
>
> Cheers
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array tail destructuring

2016-10-01 Thread Dmitry Soshnikov
Yeah, because it's not a pattern patching, and access to array elements may
have side effects, it's seems hard to specify/implement. Otherwise,
destructuring might analyze the pattern, see the last element is required,
extract it, and then do iteration for others.

Dmitry

On Saturday, October 1, 2016, Michael Theriot 
wrote:

> I think this is because there's no universal way of determining when an
> iterator ends. The only way this could work for all iterators would require
> popping values off of `a` after they've been added.
>
> On Sat, Oct 1, 2016 at 6:17 AM, Cyril Auburtin  > wrote:
>
>> It was possibly already discussed, but why isn't:
>> ```
>> var [...a, last] = [1,2,3];
>> ```
>> supported?
>>
>> I don't see the problem, as long as there's one ... only
>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> 
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Additional methods for Objects (like Arrays)

2016-01-29 Thread Dmitry Soshnikov
On Friday, January 29, 2016, Rick Waldron  wrote:

>
>
> On Fri, Jan 29, 2016 at 6:08 PM Kaustubh Karkare <
> kaustubh.kark...@gmail.com
> > wrote:
>
>> I have recently come to feel the need for Object.map, which is like
>> Array.map,
>> except that it receive keys instead of indices.
>>
>> Object.prototype.map = function(mapFn, context) {
>>   return Object.keys(this)
>> .reduce(function(result, key) {
>>   result[key] = mapFn.call(context, this[key], key, this);
>>   return result;
>> }, {});
>> };
>>
>> Without this, I frequently do the exact same thing as the above manually,
>> which leads to unnecessary code duplication.
>>
>> Given that, it might make sense to match other methods from
>> Array.prototype
>>
>> Object.map
>> Object.filter
>> Object.every
>> Object.some
>> Object.reduce
>> Object.find
>> Object.findKey // like Array.findIndex
>>
>
>
> Are these necessary given the introduction of Object.values() and
> Object.entries()? https://github.com/tc39/proposal-object-values-entries
>
>
I think what Kaustubh is proposing is that the result is a transformed
object/map, not an array. See the reduce method in his implementation.

Dmitry



> Rick
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Additional methods for Objects (like Arrays)

2016-01-29 Thread Dmitry Soshnikov
Yeah, some languages have this functionality available for maps, e.g.
Erlang http://erlang.org/doc/man/maps.html#map-2. Might be a good addition,
although considering `Map` instead of `Object` is worth as well. (although,
when we were discussing of adding `Map.prototype.map/filter`, it was
decided that it's better to add them on iterators).

Dmitry

On Fri, Jan 29, 2016 at 3:07 PM, Kaustubh Karkare <
kaustubh.kark...@gmail.com> wrote:

> I have recently come to feel the need for Object.map, which is like
> Array.map,
> except that it receive keys instead of indices.
>
> Object.prototype.map = function(mapFn, context) {
>   return Object.keys(this)
> .reduce(function(result, key) {
>   result[key] = mapFn.call(context, this[key], key, this);
>   return result;
> }, {});
> };
>
> Without this, I frequently do the exact same thing as the above manually,
> which leads to unnecessary code duplication.
>
> Given that, it might make sense to match other methods from Array.prototype
>
> Object.map
> Object.filter
> Object.every
> Object.some
> Object.reduce
> Object.find
> Object.findKey // like Array.findIndex
>
> Note that wherever applicable, the ordering is non-deterministic.
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Additional methods for Objects (like Arrays)

2016-01-29 Thread Dmitry Soshnikov
On Fri, Jan 29, 2016 at 3:07 PM, Kaustubh Karkare <
kaustubh.kark...@gmail.com> wrote:

> I have recently come to feel the need for Object.map, which is like
> Array.map,
> except that it receive keys instead of indices.
>
> Object.prototype.map = function(mapFn, context) {
>   return Object.keys(this)
> .reduce(function(result, key) {
>   result[key] = mapFn.call(context, this[key], key, this);
>   return result;
> }, {});
> };
>
>
Also a potential issue of placing it on `Object.prototype` is that other
things will inherit it, including unrelated (like strings, regexps,
functions, etc). By this reason seems iterator methods `values`, `keys`,
and `entries` weren't added in ES6 to `Object.prototype`.

Dmitry



> Without this, I frequently do the exact same thing as the above manually,
> which leads to unnecessary code duplication.
>
> Given that, it might make sense to match other methods from Array.prototype
>
> Object.map
> Object.filter
> Object.every
> Object.some
> Object.reduce
> Object.find
> Object.findKey // like Array.findIndex
>
> Note that wherever applicable, the ordering is non-deterministic.
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Javascript Language feature Idea

2016-01-22 Thread Dmitry Soshnikov
On Fri, Jan 22, 2016 at 9:53 AM, RacerD123  wrote:

> In other programming languages such as python, you can specify the last
> element of a list with "list[-1]" but in javascript you have to do
> "list[list.length-1]". Is there maybe a way to make this feature in
> javascript?
>
>
This could be a good addition, although `slice` may work as well. This has
been discussed previously as well in the last 4-5 years. In addition with
non-enumerable properties you can just monkey-patch `Array.prototype` with
the `peek` or `last` method. I guess approach when some library forces some
method to widely used, can be a good candidate for adding it to the spec
(this how it was with `Function.prototype.bind`, e.g., although today
monkey-patching is a bad practice of course).

In addition, you can monkey-patch just `-1`, and other indexes, e.g. a gist
from 5 years old, when a similar topic was proposed here:
https://gist.github.com/DmitrySoshnikov/984921

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Legitimate uses of IIFEs?

2015-12-20 Thread Dmitry Soshnikov
But how would you make an async entry point? Say, you have couple of async
functions which you imported, they should be ran sequentily, depending on
each other:

let user = await fetchUser(id);
let scores = user.scores.map(score => score.latest);
let data = await fetchData(scores);

What should be an entry point to this async code, if thete is no top-level
await?

Having an async IIFE for the purpose of an entry point seems fits well
here. How else would you do this, except an async function declaration, and
further its execution?

function asyncEntryPoint() {
  // await here
}

asyncEntryPoint();
  // .then(...); // not needed

Dmitry
On Dec 20, 2015 13:57, "Mat At Bread" <br...@mailed.me.uk> wrote:

> I don't dispute you can do it, I just don't see it as necessary, or at
> least any more necessary than using an IIFE to collect together synchronous
> logic. The creation of the scope is not a factor here.
>
> On 20 December 2015 9:54:59 pm Dmitry Soshnikov <
> dmitry.soshni...@gmail.com> wrote:
>
>>
>>
>> On Sunday, December 20, 2015, <br...@mailed.me.uk> wrote:
>>
>>> You're quite right, which demonstrates the lack of necessity for a
>>> top-level await (FYI, I find the inconsistency irritating but
>>> understandable), so I still maintain this is not a _required_ use for an
>>> IIAFE - there is no reason to create an async function to invoke another
>>> async function; one can simply invoke it, and if the result/completion is
>>> required, use it's ,then() memberbut there's no need/advantage to
>>> wrapping such an invocation in an IIAFE, right?
>>>
>>>
>> The use case is valid, there was no mistakes. We use async IIFEs as an
>> "entry point" to async code: you can await there, do intermediate
>> calculations with temporary variables, again awai, etc (Promise.all has a
>> different use case).
>>
>> Dmitry
>>
>>
>>
>>>
>>> On 20 December 2015 13:40:30 -00:00, Forbes Lindesay <
>>> for...@lindesay.co.uk> wrote:
>>>
>>> Promises are eager.  That is, they do the work and resolve whether you
>>> await them or not.  If you want to handle exceptions, you need to call
>>> .then and provide an error handler, but other than that it's totally ok to
>>> not bother waiting for a promise.
>>>
>>> On 19 Dec 2015, at 22:02, Mat At Bread <br...@mailed.me.uk> wrote:
>>>
>>> Which is what I said, I hope. Use the .then for top-level invitation.
>>> Dimitry's example wouldn't resolve the Promise
>>>
>>> On 19 December 2015 9:24:04 pm Fabrício Matté <ultco...@gmail.com>
>>> wrote:
>>>
>>> @bread I see you are referencing Dmitry's sample, but why do you say it
>>> won't work? AFAIK async functions return promises, so you don't necessarily
>>> need a top-level `await`. I believe this (extremely ugly) sample should
>>> work:
>>>
>>> ```js
>>> function f(cb) {
>>>   (async function() {
>>> // await here
>>>   })().then(v => cb(null, v), cb);
>>> }
>>> ```
>>>
>>> /fm
>>>
>>> On Sat, Dec 19, 2015 at 7:11 PM, <br...@mailed.me.uk> wrote:
>>>
>>> That’s not going to work. The correct form still requires an (illegal)
>>> top-level await:
>>>
>>> await (async function() {
>>> // await here
>>> })();
>>>
>>> The easiest way to spawn a top-level async function is:
>>>
>>> here.then(function(result){},function(error){}) ;
>>>
>>> On 19 December 2015 20:14:44 -00:00, Dmitry Soshnikov <
>>> dmitry.soshni...@gmail.com> wrote:
>>>
>>>
>>>
>>> On Saturday, December 19, 2015, Šime Vidas <sime.vi...@gmail.com> wrote:
>>>
>>> With block statements + let/const, IIFEs are no longer needed to emulate
>>> block-scoped variables. That got me thinking, are there other uses of
>>> IIFEs, or are they no longer needed?
>>> I’ve checked my code and found instances of this pattern:
>>>
>>> var foo = (function () {
>>> var a, b, c; // helper variables
>>> // some computation
>>> return /* final value of foo */;
>>> }());
>>> Btw, there is a "do expression" proposal (stage 0) [1] for this type of
>>> pattern.
>>> Anything else?
>>>
>>>
>>> FWIW, one of the still valid use cases is async IIFE, to spawn an async
>>> code (since there's no yet top-level async/await)
>>>
>>> (async function() {
>>>   // await here
>>> })();
>>>
>>> Dmitry
>>>
>>>
>>>
>>> ___
>>> es-discuss mailing list
>>> es-discuss@mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>> ___
>>> es-discuss mailing list
>>> es-discuss@mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Legitimate uses of IIFEs?

2015-12-20 Thread Dmitry Soshnikov
On Sunday, December 20, 2015, <br...@mailed.me.uk> wrote:

> You're quite right, which demonstrates the lack of necessity for a
> top-level await (FYI, I find the inconsistency irritating but
> understandable), so I still maintain this is not a _required_ use for an
> IIAFE - there is no reason to create an async function to invoke another
> async function; one can simply invoke it, and if the result/completion is
> required, use it's ,then() memberbut there's no need/advantage to
> wrapping such an invocation in an IIAFE, right?
>
>
The use case is valid, there was no mistakes. We use async IIFEs as an
"entry point" to async code: you can await there, do intermediate
calculations with temporary variables, again awai, etc (Promise.all has a
different use case).

Dmitry



>
> On 20 December 2015 13:40:30 -00:00, Forbes Lindesay <
> for...@lindesay.co.uk
> <javascript:_e(%7B%7D,'cvml','for...@lindesay.co.uk');>> wrote:
>
> Promises are eager.  That is, they do the work and resolve whether you
> await them or not.  If you want to handle exceptions, you need to call
> .then and provide an error handler, but other than that it's totally ok to
> not bother waiting for a promise.
>
> On 19 Dec 2015, at 22:02, Mat At Bread <br...@mailed.me.uk
> <javascript:_e(%7B%7D,'cvml','br...@mailed.me.uk');>> wrote:
>
> Which is what I said, I hope. Use the .then for top-level invitation.
> Dimitry's example wouldn't resolve the Promise
>
> On 19 December 2015 9:24:04 pm Fabrício Matté <ultco...@gmail.com
> <javascript:_e(%7B%7D,'cvml','ultco...@gmail.com');>> wrote:
>
> @bread I see you are referencing Dmitry's sample, but why do you say it
> won't work? AFAIK async functions return promises, so you don't necessarily
> need a top-level `await`. I believe this (extremely ugly) sample should
> work:
>
> ```js
> function f(cb) {
>   (async function() {
> // await here
>   })().then(v => cb(null, v), cb);
> }
> ```
>
> /fm
>
> On Sat, Dec 19, 2015 at 7:11 PM, <br...@mailed.me.uk
> <javascript:_e(%7B%7D,'cvml','br...@mailed.me.uk');>> wrote:
>
> That’s not going to work. The correct form still requires an (illegal)
> top-level await:
>
> await (async function() {
> // await here
> })();
>
> The easiest way to spawn a top-level async function is:
>
> here.then(function(result){},function(error){}) ;
>
> On 19 December 2015 20:14:44 -00:00, Dmitry Soshnikov <
> dmitry.soshni...@gmail.com
> <javascript:_e(%7B%7D,'cvml','dmitry.soshni...@gmail.com');>> wrote:
>
>
>
> On Saturday, December 19, 2015, Šime Vidas <sime.vi...@gmail.com
> <javascript:_e(%7B%7D,'cvml','sime.vi...@gmail.com');>> wrote:
>
> With block statements + let/const, IIFEs are no longer needed to emulate
> block-scoped variables. That got me thinking, are there other uses of
> IIFEs, or are they no longer needed?
> I’ve checked my code and found instances of this pattern:
>
> var foo = (function () {
> var a, b, c; // helper variables
> // some computation
> return /* final value of foo */;
> }());
> Btw, there is a "do expression" proposal (stage 0) [1] for this type of
> pattern.
> Anything else?
>
>
> FWIW, one of the still valid use cases is async IIFE, to spawn an async
> code (since there's no yet top-level async/await)
>
> (async function() {
>   // await here
> })();
>
> Dmitry
>
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> <javascript:_e(%7B%7D,'cvml','es-discuss@mozilla.org');>
> https://mail.mozilla.org/listinfo/es-discuss
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> <javascript:_e(%7B%7D,'cvml','es-discuss@mozilla.org');>
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Legitimate uses of IIFEs?

2015-12-19 Thread Dmitry Soshnikov
On Saturday, December 19, 2015, Šime Vidas  wrote:

> With block statements + let/const, IIFEs are no longer needed to emulate
> block-scoped variables. That got me thinking, are there other uses of
> IIFEs, or are they no longer needed?
>
> I’ve checked my code and found instances of this pattern:
>
> var foo = (function () {
> var a, b, c; // helper variables
> // some computation
> return /* final value of foo */;
> }());
>
> Btw, there is a "do expression" proposal (stage 0) [1] for this type of
> pattern.
>
> Anything else?
>

FWIW, one of the still valid use cases is async IIFE, to spawn an async
code (since there's no yet top-level async/await)

(async function() {
  // await here
})();

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Take props from object

2015-08-19 Thread Dmitry Soshnikov
Hey guys,

From an internal conversation, we've received a question, and as a follow
up, the proposal of take needed props from an object.

Currently if you need to take some properties from an object, you'd do:

```javascript
var foo = {x: bar.x, y: bar.y, z: bar.z};
```

With possible shorthand it even could be (I guess someone proposed this
already at some point):

```javascript
var foo = {bar.x, bar.y, bar.z};
```

Sometimes one could also do with destructuring and shorhands, but these are
two actions

```javascript
var {x, y, z} = bar;
var foo = {x, y, z};
```

And the take props operator combine those approaches, and may look like
an import statement from a module, just without the `import` keyword:

```javascript
var foo = {x, y, z} from bar;
```

I personally liked this strawman, it smoothes the border between a module
and an object (which is also a module/namespace, from which we can import
needed exports).

I haven't checked yet the grammar, seems should be fine from the first
glance.

Thoughts?

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Take props from object

2015-08-19 Thread Dmitry Soshnikov
On Wed, Aug 19, 2015 at 9:22 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:



 ```javascript
 var foo = {x, y, z} from bar;
 ```

 I haven't checked yet the grammar, seems should be fine from the first
 glance.


Yeah, it should be parsed first as an object literal, and then to the take
props operator if the lookahead is `from`.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: String.prototype.trimRight/trimLeft

2015-07-27 Thread Dmitry Soshnikov
OK, it was added to the agenda for the next meeting (will be presented
by Sebastian Markbage), so can be discussed in detail. I agree that
start, and end are now probably better fit (because of i18n, and a
strong correlation with startsWith and endsWith). We can probably
ignore the de-facto shipped in browsers, they will just implement in
addition `trimStart` and `trimEnd`, and eventually deprecate the right
and left.

Dmitry

On Tue, Jul 21, 2015 at 12:02 AM, Claude Pache claude.pa...@gmail.com
wrote:


  Le 21 juil. 2015 à 08:28, Jordan Harband ljh...@gmail.com a écrit :
 
  On the contrary -left always begins at index 0 - start is sometimes
 index 0, sometimes index (length - 1).

 Counter-example: ES6 methods `String#startsWith` and `String#endsWith` are
 named correctly.

  I think left and right are the right names; start and end would
 require unicode bidirectional stuff.

 No, because characters in Unicode strings are ordered logically, not
 visually.

 —Claude

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: String.prototype.trimRight/trimLeft

2015-07-20 Thread Dmitry Soshnikov
Will somebody be so kind to present this on the following meeting for me, I
don't have an ability to attend, and the change is pretty small (July 28th,
2015)?

People were asking, and we'd like to polyfill it instead of doing regexp
replaces. Again the spec is here:
https://gist.github.com/DmitrySoshnikov/65a2070477fffb465048

Thanks!

Dmitry

On Wed, Mar 18, 2015 at 2:26 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 OK, the spec is here:
 https://gist.github.com/DmitrySoshnikov/65a2070477fffb465048 Will
 appreciate review and corrections if needed.

 Dmitry

 On Tue, Mar 17, 2015 at 7:36 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 Sounds good. Yeah, I'll spec it, and add the test.

 Dmitry


 On Tuesday, March 17, 2015, Domenic Denicola d...@domenic.me wrote:

  Yeah, this seems like a shoe-in for ES7. It will probably be able to
 advance through the stages *very* quickly given that it already has
 three (four?) shipping implementations.



 Someone just needs to write up a formal spec (using Ecmarkdown! ^_^) and
 test262 tests. The only snag would be if you find non-interoperable
 behavior between browsers in the course of writing those tests, and need to
 get some patches accepted before you can reach stage 4.



 *From:* es-discuss [mailto:es-discuss-boun...@mozilla.org] *On Behalf
 Of *Dmitry Soshnikov
 *Sent:* Wednesday, March 18, 2015 05:02
 *To:* Tab Atkins Jr.
 *Cc:* es-discuss
 *Subject:* Re: String.prototype.trimRight/trimLeft



 Right, so from the several feedback I had so far, it seems it will make
 sense just to add to ES7? In this case we'll be able to polyfill now, the
 spec'ing it will be trivial (I'll add the spec).



 I guess we just need to confirm it's good to go to ES7?



 Dmitry



 On Tue, Mar 17, 2015 at 12:21 PM, Tab Atkins Jr. jackalm...@gmail.com
 wrote:

  On Mon, Mar 16, 2015 at 11:07 PM, Leon Arnott leonarn...@gmail.com
 wrote:
  I believe opinion hasn't shifted since it was discussed
  [previously](
 https://esdiscuss.org/topic/standardizing-more-de-facto-functions)
  - in short, show me the cowpath. (But, I've just learned that the IE
  Technical Preview now supports trimLeft/trimRight, so there'll soon be
  support for it in all the major engines. Maybe the cows are there after
  all.)

 I use both lstrip() and rstrip() in Bikeshed (a Python project):


 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=lstriptype=Code

 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=rstriptype=Code

 In particular, lstrip() is used when I'm separating a key and value; I
 don't want to mess with the value much at all, just pull off the
 whitespace at the start.  rstrip() is used when I know I don't need to
 strip from the left side, because I'm just pulling off newlines or
 something, so might as well let the program avoid even trying.

 ~TJ





___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ECMAScript 2015 is now an Ecma Standard

2015-06-17 Thread Dmitry Soshnikov
Congrats the whole TC-39, and special thanks to Allen Wirfs-Brock for the
actual great editorial work on the spec!

Dmitry

On Wed, Jun 17, 2015 at 9:46 AM, Allen Wirfs-Brock al...@wirfs-brock.com
wrote:

 Ecma international has announced that its General Assembly has approved
 ECMA-262-6 *The ECMAScript 2015 Language Specification* as an Ecma
 standard  http://www.ecma-international.org/news/index.html

 The official document is now available from Ecma in HTML at
 http://www.ecma-international.org/ecma-262/6.0

 and as a PDF at
 http://www.ecma-international.org/ecma-262/6.0/ECMA-262.pdf

 I recommend that  people immediately start using the  Ecma HTML version in
 discussion where they need to link references to sections of the
 specification.

 Allen


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Can't do push in forEach

2015-05-15 Thread Dmitry Soshnikov
In ES2015 (available today via transpilers), one can do:

arr1.push(...arr2);

Dmitry

On Thursday, May 14, 2015, Emanuel Allen emanuelal...@hotmail.com wrote:

 kudos to you sir or ma'am, It work!

 var arr = [9,8,7,'a','b','c'], arr2 = [];

 [].push.apply(arr2,arr);

 arr2;// [9,8,7,'a','b','c']

 JS4L

 On May 14, 2015, at 6:40 PM, Michael Haufe t...@thenewobjective.com
 javascript:_e(%7B%7D,'cvml','t...@thenewobjective.com'); wrote:

 ...but you can do this:

 [].push.apply(arr1,arr2);

 On Thu, May 14, 2015 at 9:25 AM, Emanuel Allen emanuelal...@hotmail.com
 javascript:_e(%7B%7D,'cvml','emanuelal...@hotmail.com'); wrote:

 Surprise that I can't do arr1.forEeach(arr2.push);

 Will throw an error.

 Using bind as:

 push = arr2.bind(push);
 arr1.forEeach(push);

 Works... And not work. Seem to push individual elements and after every
 second element, it'll push the hold array.. And after and before each index
 that hold the array there are duplicate of that element preceding and
 following:

 [1,2,array,2,3]//not this is with shift method
 [1,2,array,3,2]//note that this is with push


 JS4L
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 javascript:_e(%7B%7D,'cvml','es-discuss@mozilla.org');
 https://mail.mozilla.org/listinfo/es-discuss



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Final ES6 Draft

2015-04-17 Thread Dmitry Soshnikov
Thanks Allen!

Dmitry

On Thursday, April 16, 2015, Allen Wirfs-Brock al...@wirfs-brock.com
wrote:

 The final ES6 ECMAScript 2014 specification draft has been completed and
 submitted to the Ecma GA for their consideration and review prior to their
 June vote to approve it as a standard.

 The final draft is available at
 http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#final_draft


 The only significant technical change in this draft is some tweaks to
 completion value generation within iteration statements.  These tweaks
 ensure that unroll a loop does not change the resulting completion values.

 Other changes are minor editorial corrections including a few Ecma styling
 conformance issues.

 It will still be possible to make a few very minor editorial corrections
 before publishings the standard. So please continue to report any bugs or
 typos you find to bugs.ecmascript.org.

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: generator function requirements

2015-04-12 Thread Dmitry Soshnikov
On Sun, Apr 12, 2015 at 4:53 PM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Sun, Apr 12, 2015 at 11:59 AM Mark Volkmann r.mark.volkm...@gmail.com
 wrote:

 I couldn't find this in spec. Is it required for generator functions to
 return an object that is both iterable (has Symbol.iterator method) and an
 iterator (has next method). It seems Babel does this, but I want verify
 whether that is required.


 The object that's returned by a generator function conforms to both the
 Iterator and Iterable interfaces.


As any other iterator of the built-ins (unless I'm not aware of specific
cases). I.e. an enough description is: an object is returned by a generator
function is an _iterator_ (and that it conforms also the iterable
interfaces this should go without saying, since all iterators do;
user-level iterators may deviate from this invariant though).

Dmitry


 -
 https://people.mozilla.org/~jorendorff/es6-draft.html#sec-iterable-interface
 -
 https://people.mozilla.org/~jorendorff/es6-draft.html#sec-iterator-interface

 Rick


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: The ES6 iteration protocol

2015-04-06 Thread Dmitry Soshnikov
I guess all built-in iterators return themselves for `Symbol.iterator`
protocol. So they are all singletons. I described in detail where
confusion/substitution of concepts happens in that analysis in the recent
two comments.

Dmitry

On Mon, Apr 6, 2015 at 1:07 PM, joe joe...@gmail.com wrote:

 Regardless of what the spec says, you cannot avoid singleton iterators in
 real-world code.  In my opinion, the spec should refrain from specifying
 when object creation happens within the iteration protocol, wait for the
 relevant code and contract patterns to develop and then include something
 in ES7.

 On Sun, Mar 29, 2015 at 12:08 AM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 Good write up, although fresh vs singleton topic doesn't make sense,
 and doesn't reflect the spec. I responded on the gist.

 Dmitry

 On Sat, Mar 28, 2015 at 4:41 AM, Axel Rauschmayer a...@rauschma.de
 wrote:

 FWIW: I have written down my understanding of the ES6 iteration protocol
 (shaped by discussions I had on this mailing list).

 https://gist.github.com/rauschma/73e5f86a595b7709f39e

 --
 Dr. Axel Rauschmayer
 a...@rauschma.de
 rauschma.de




 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: The ES6 iteration protocol

2015-04-06 Thread Dmitry Soshnikov
Exactly, that's what I tried to explain. Since in one case it considers
just an iterable (an array), and in other case -- an iterator (which is by
coincidence is also an iterable). But an array's iterator is an iterable
as well, and also always returns itself for iterator protocol.

Yeah, the self-iterable makes much more sense in this case.

Dmitry

On Monday, April 6, 2015, Allen Wirfs-Brock al...@wirfs-brock.com wrote:


  On Apr 6, 2015, at 2:23 PM, Dmitry Soshnikov dmitry.soshni...@gmail.com
 javascript:; wrote:
 
  I guess all built-in iterators return themselves for `Symbol.iterator`
 protocol. So they are all singletons. I described in detail where
 confusion/substitution of concepts happens in that analysis in the recent
 two comments.
 

 I don’t think “singleton” is the correct term for the concept that Axel is
 trying to describe.  A “singleton” is normally an kind of object for which
 there is only a single instances.  There may be many instances of, for
 example %ArrayIterator%, so it isn’t correct to call %ArrayIterator% a
 singleton

 What Axel is describing might be characterized as “self iterable”, it
 returns itself when recieving a Symbol.iterator request.

 Allen


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: The ES6 iteration protocol

2015-03-29 Thread Dmitry Soshnikov
Good write up, although fresh vs singleton topic doesn't make sense, and
doesn't reflect the spec. I responded on the gist.

Dmitry

On Sat, Mar 28, 2015 at 4:41 AM, Axel Rauschmayer a...@rauschma.de wrote:

 FWIW: I have written down my understanding of the ES6 iteration protocol
 (shaped by discussions I had on this mailing list).

 https://gist.github.com/rauschma/73e5f86a595b7709f39e

 --
 Dr. Axel Rauschmayer
 a...@rauschma.de
 rauschma.de




 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: String.prototype.trimRight/trimLeft

2015-03-18 Thread Dmitry Soshnikov
OK, the spec is here:
https://gist.github.com/DmitrySoshnikov/65a2070477fffb465048 Will
appreciate review and corrections if needed.

Dmitry

On Tue, Mar 17, 2015 at 7:36 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 Sounds good. Yeah, I'll spec it, and add the test.

 Dmitry


 On Tuesday, March 17, 2015, Domenic Denicola d...@domenic.me wrote:

  Yeah, this seems like a shoe-in for ES7. It will probably be able to
 advance through the stages *very* quickly given that it already has
 three (four?) shipping implementations.



 Someone just needs to write up a formal spec (using Ecmarkdown! ^_^) and
 test262 tests. The only snag would be if you find non-interoperable
 behavior between browsers in the course of writing those tests, and need to
 get some patches accepted before you can reach stage 4.



 *From:* es-discuss [mailto:es-discuss-boun...@mozilla.org] *On Behalf Of
 *Dmitry Soshnikov
 *Sent:* Wednesday, March 18, 2015 05:02
 *To:* Tab Atkins Jr.
 *Cc:* es-discuss
 *Subject:* Re: String.prototype.trimRight/trimLeft



 Right, so from the several feedback I had so far, it seems it will make
 sense just to add to ES7? In this case we'll be able to polyfill now, the
 spec'ing it will be trivial (I'll add the spec).



 I guess we just need to confirm it's good to go to ES7?



 Dmitry



 On Tue, Mar 17, 2015 at 12:21 PM, Tab Atkins Jr. jackalm...@gmail.com
 wrote:

  On Mon, Mar 16, 2015 at 11:07 PM, Leon Arnott leonarn...@gmail.com
 wrote:
  I believe opinion hasn't shifted since it was discussed
  [previously](
 https://esdiscuss.org/topic/standardizing-more-de-facto-functions)
  - in short, show me the cowpath. (But, I've just learned that the IE
  Technical Preview now supports trimLeft/trimRight, so there'll soon be
  support for it in all the major engines. Maybe the cows are there after
  all.)

 I use both lstrip() and rstrip() in Bikeshed (a Python project):


 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=lstriptype=Code

 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=rstriptype=Code

 In particular, lstrip() is used when I'm separating a key and value; I
 don't want to mess with the value much at all, just pull off the
 whitespace at the start.  rstrip() is used when I know I don't need to
 strip from the left side, because I'm just pulling off newlines or
 something, so might as well let the program avoid even trying.

 ~TJ




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: String.prototype.trimRight/trimLeft

2015-03-17 Thread Dmitry Soshnikov
Right, so from the several feedback I had so far, it seems it will make
sense just to add to ES7? In this case we'll be able to polyfill now, the
spec'ing it will be trivial (I'll add the spec).

I guess we just need to confirm it's good to go to ES7?

Dmitry

On Tue, Mar 17, 2015 at 12:21 PM, Tab Atkins Jr. jackalm...@gmail.com
wrote:

 On Mon, Mar 16, 2015 at 11:07 PM, Leon Arnott leonarn...@gmail.com
 wrote:
  I believe opinion hasn't shifted since it was discussed
  [previously](
 https://esdiscuss.org/topic/standardizing-more-de-facto-functions)
  - in short, show me the cowpath. (But, I've just learned that the IE
  Technical Preview now supports trimLeft/trimRight, so there'll soon be
  support for it in all the major engines. Maybe the cows are there after
  all.)

 I use both lstrip() and rstrip() in Bikeshed (a Python project):


 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=lstriptype=Code

 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=rstriptype=Code

 In particular, lstrip() is used when I'm separating a key and value; I
 don't want to mess with the value much at all, just pull off the
 whitespace at the start.  rstrip() is used when I know I don't need to
 strip from the left side, because I'm just pulling off newlines or
 something, so might as well let the program avoid even trying.

 ~TJ

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: String.prototype.trimRight/trimLeft

2015-03-17 Thread Dmitry Soshnikov
Sounds good. Yeah, I'll spec it, and add the test.

Dmitry

On Tuesday, March 17, 2015, Domenic Denicola d...@domenic.me wrote:

  Yeah, this seems like a shoe-in for ES7. It will probably be able to
 advance through the stages *very* quickly given that it already has three
 (four?) shipping implementations.



 Someone just needs to write up a formal spec (using Ecmarkdown! ^_^) and
 test262 tests. The only snag would be if you find non-interoperable
 behavior between browsers in the course of writing those tests, and need to
 get some patches accepted before you can reach stage 4.



 *From:* es-discuss [mailto:es-discuss-boun...@mozilla.org
 javascript:_e(%7B%7D,'cvml','es-discuss-boun...@mozilla.org');] *On
 Behalf Of *Dmitry Soshnikov
 *Sent:* Wednesday, March 18, 2015 05:02
 *To:* Tab Atkins Jr.
 *Cc:* es-discuss
 *Subject:* Re: String.prototype.trimRight/trimLeft



 Right, so from the several feedback I had so far, it seems it will make
 sense just to add to ES7? In this case we'll be able to polyfill now, the
 spec'ing it will be trivial (I'll add the spec).



 I guess we just need to confirm it's good to go to ES7?



 Dmitry



 On Tue, Mar 17, 2015 at 12:21 PM, Tab Atkins Jr. jackalm...@gmail.com
 javascript:_e(%7B%7D,'cvml','jackalm...@gmail.com'); wrote:

  On Mon, Mar 16, 2015 at 11:07 PM, Leon Arnott leonarn...@gmail.com
 javascript:_e(%7B%7D,'cvml','leonarn...@gmail.com'); wrote:
  I believe opinion hasn't shifted since it was discussed
  [previously](
 https://esdiscuss.org/topic/standardizing-more-de-facto-functions)
  - in short, show me the cowpath. (But, I've just learned that the IE
  Technical Preview now supports trimLeft/trimRight, so there'll soon be
  support for it in all the major engines. Maybe the cows are there after
  all.)

 I use both lstrip() and rstrip() in Bikeshed (a Python project):


 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=lstriptype=Code

 https://github.com/tabatkins/bikeshed/search?utf8=%E2%9C%93q=rstriptype=Code

 In particular, lstrip() is used when I'm separating a key and value; I
 don't want to mess with the value much at all, just pull off the
 whitespace at the start.  rstrip() is used when I know I don't need to
 strip from the left side, because I'm just pulling off newlines or
 something, so might as well let the program avoid even trying.

 ~TJ



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


String.prototype.trimRight/trimLeft

2015-03-16 Thread Dmitry Soshnikov
Hi,

Just got a question why don't we polyfill `trimLeft` and `trimRight` for
strings, and have only `trim` (and the answer is -- because it's not part
of ES5/ES6).

Just thinking could it be a valid cases when a dev may want to trim only
form right still keeping e.g. the precalculated padding on the left (seems
legit)?

MDN mentions them [1], [2], though as non-standard. What stopping both
methods to be included?

[1]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimLeft
[2]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: How to fix the `class` keyword

2015-03-04 Thread Dmitry Soshnikov
There is a trap one could fall into, after reading one classic or even
authoritive book. After that it might seem one understood the essence of
everything.

For fairness, there were couple of valid points noticed:
composition/aggregation (will be achieved, and already now can be, by
mixins), and, probably, that you'll have to refactor call sites if you
decide to switch to the raw factory (that's why eg Python chose to
instantiate without 'new' keyword).

Other than that, yes, factory is just a desugarred class pattern, and yes,
sugar matters if you want to design a practical language. In case of
class-based code reuse, prototypes were also desugarred version of it
(that's why JS at some point was unexplained, and as a result made it
harder to be practical quicker). Eg in my class I give prototypes as an
advanced topic now, since it's just an implementation detail (the same
again as in Python, which is also delegation-based).

The most valuable advice would be from Eric Arvidsson - just to design your
language (likely, to be a compiler writer is easier nowadays), and
exactly there you'll see how sugar matters.

Dmitry

On Wednesday, March 4, 2015, Eric Elliott e...@paralleldrive.com wrote:


 I've already posted this on my Medium blog here:
 https://medium.com/@_ericelliott/how-to-fix-the-es6-class-keyword-2d42bb3f4caf

 It seems inevitable that the `*class*` keyword in JavaScript is going to
 catch on, but that’s a problem because it’s fundamentally broken in many
 ways.

 Now that it’s out there and people are using it, it seems like the only
 logical way forward is to *try to make it better for everybody*.

 In JavaScript, *any function can instantiate and return objects.* When
 you do so without a constructor, it’s called a *factory function*. The
 new `*class*` syntax *can’t compete with the power and flexibility of
 factories* — specifically stamps, and object pools are not the only
 factory use-case.

 There is a whole section on object construction in the GoF “Design
 Patterns” book
 http://www.amazon.com/gp/product/0201633612?ie=UTF8camp=213733creative=393185creativeASIN=0201633612linkCode=shrtag=eejs-20linkId=XXUP5DXMFH5VS2UI
  which
 exist only to get around the limitations of constructors and classes.

 See also: Three Different Kinds of Prototypal OO.
 http://ericleads.com/2013/02/fluent-javascript-three-different-kinds-of-prototypal-oo/

 The bottom line: *Class doesn’t give you any power* that isn’t already
 supplied by *factory functions* and the *prototypal OO* built into the
 language. All you’re doing when you create a class is opting into a *less
 powerfull, less flexible mechanism* and *a whole lot of pitfalls and
 pain.*
 https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3

 Is there any hope that the `*class*` keyword will ever be useful? *Maybe.*
 Why should we bother?


 Why don’t we just create a lint rule and move on?

 *The `class` keyword is creating a rift* in the JavaScript community. I
 for one have plans to create an ESLint config that prohibits `*class*`
 and share it as far and as wide as I can — and since I’m building a
 community of JavaScript developers that currently includes ~40,000 people,
 that’s far enough to have an impact.

 *Classes could be useful*. What if we want to build abstractions on top
 of it? What if we want to do more things in the language itself that could
 benefit with `*class*` integration (such as built-in *traits*)?

 *We could make these changes opt-in* by adding config to the class
 itself. That would prevent breaking changes and hopefully make the whole
 community happy. As it stands, we're just making people with classical
 inheritance backgrounds happy -- *at least until they fall into one of
 the many pitfalls ahead of them.*

 *Shouldn’t the entire JavaScript community benefit from `class`?*
 *How to Fix `class`*

1. *Make class inheritance compositional* similar to the way stamps
are composed.

 http://chimera.labs.oreilly.com/books/123400262/ch03.html#prototypal_inheritance_with_stamps
  In
other words, change the behavior of `*extend*`, or *deprecate `extend`* and
replace it with something like a *`compose` keyword* that can *compose
any number of classes.*
2. *Deprecate `new`. *`*new*` violates both the *substitution
principle* and the *open / closed principle*. The `*new*` keyword is
destructive because *it adds zero value to the language*, and it *couples
all callers to the details of object instantiation*. If you start with
a class that requires `*new*` (all classes in ES6) and you later
decide you need to use a factory instead of a class, *you can’t make
the change without refactoring all callers.* This is especially
problematic for shared libraries and public interfaces, because *you
may not have access to all of the code using the class.* You may think
it doesn’t do any harm to just call a factory function with the `*new*`

Re: short-circuiting Array.prototype.reduce

2015-02-23 Thread Dmitry Soshnikov
On Mon, Feb 23, 2015 at 10:09 AM, Andreas Rossberg rossb...@google.com
wrote:

 On 23 February 2015 at 16:22, Mark S. Miller erig...@google.com wrote:

 We still an an option open to us, that would merely compatibly remove a
 restriction from the language rather than add a feature: Allow labels to
 remain visible across function boundaries, or at least across arrow
 function boundaries. Then one could break-to-label to a label of a
 lexically enclosing function.

 This has repeatedly died in committee before because it does raise
 another case for implementors: Once the execution context of that label has
 completed, an attempt to break to that label must instead throw an error.
 I've never understood why this extra case was a show stopper.


 I opposed it (and still firmly do) not just because this has considerable
 implementation complexity (each call could then have an arbitrary and
 unknown number of exit points, not just two, and I don't even want to
 imagine what that would do to our control graph) -- that is just a
 consequence of the real problem, which is that this is an unstructured form
 of non-local control transfer, a half-way, half-broken form of
 continuations. If you want continuations, add real continuations.


 On Sun, Feb 22, 2015 at 11:36 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 The technical reason for this I guess, is that JS doesn't have TCP
 blocks, that would allow you to stop iteration, and exit the `reduce`
 context right from the callback context. With TCP it would be a `return`
 statement, which in JS we have to solve throwing a special marker
 exception, which should be caught and analyzed.


 I don't see the relation to the OP's problem.


It tends to break traversing by returning a special marker. The same issue
exists e.g. with `forEach` method, not only `reduce`. The `reduce` seemed
to me just a particular case, that's why I mentioned TCP, that could solve
both.

If there are actual limitations with current state of the spec (and
complexities of implementations), it can be just that `@@reduced`. Though
then again you'd have the case like:

```javascript

$stopTraversal = {};

try {
  bigData.forEach((v) = {
if (v  100) {
  $stopTraversal._returnValue = v;
  throw $stopTraversal;
}
  });
} catch (ex) {
  if (ex === $stopTraversal) {
_data = $stopTraversal._returnValue;
  }
}

```

If this is something more convenient than:

```javascript

bigData.forEach((v) { // note, it's not an arrow, but TCP block
  if (v  100) {
_data = v;
return; // could be `exit`;
  }
});

```

For the `reduce` method it could actually `return '99+'`. That's said, if
the practical need exists specifically for the `reduce` function, I'm not
against having stop traversal mechanism only there.

Dmitry



 A break would be a very poor device for exiting a reduce, since it doesn't
 allow you to pass a result (you'd have to funnel that through assigning
 some outer variable). Also, I don't see why you can't do the same with a
 throw today.

 What Lee really wants is a partial reduce. I think this could be provided
 easily without magic symbols by using the encoding of an Either type, like
 e.g. iterators already do (though it's used here in the inverse direction).
 For example, you could imagine the following signature:

   reducePartialA, B(f: (acc: A, val: B, key: number) = {value: A, done:
 boolean}, init: A): A

 /Andreas





 From the practical perspective, yeah, it would be good to see real
 examples of how useful the feature is. Of course if we take the reason:
 exit from an hight-order iteration as soon as possible in a convenient
 way, that could sound reasonable/practical. Although, to have concrete
 examples would be good.

 However, I'd say, JS betters needs some sort of TCP blocks, which would
 solve other similar cases (and which I'm pretty sure were discussed several
 times couple of years ago). E.g. in Ruby that example would be much easier,
 and that `@@reduced` would be just simple intuitive `return`.

 Dmitry



 The only inkling of why this might be useful is an unsourced assertion
 that it's done in Clojure, for unknown reasons. The example code isn't very
 compelling either; something more real-world would be good there.
  --
 From: Lee Byron leeby...@fb.com
 Sent: ‎2015-‎02-‎23 00:58
 To: es-discuss@mozilla.org
 Subject: short-circuiting Array.prototype.reduce

  Hey all,

  I’d like to propose an addition to ES7 to add @@reduced as a way to
 short-circuit from Array.prototype.reduce.

  I’ve written up a polyfill and explanation here:

  https://github.com/leebyron/ecma-reduced

  I would love your feedback on this.

  Lee

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es

Re: short-circuiting Array.prototype.reduce

2015-02-22 Thread Dmitry Soshnikov
On Sun, Feb 22, 2015 at 10:11 PM, Domenic Denicola d...@domenic.me wrote:

  My initial feedback is that this needs a lot more why in comparison to
 the how.


The technical reason for this I guess, is that JS doesn't have TCP blocks,
that would allow you to stop iteration, and exit the `reduce` context right
from the callback context. With TCP it would be a `return` statement, which
in JS we have to solve throwing a special marker exception, which should
be caught and analyzed.

From the practical perspective, yeah, it would be good to see real examples
of how useful the feature is. Of course if we take the reason: exit from
an hight-order iteration as soon as possible in a convenient way, that
could sound reasonable/practical. Although, to have concrete examples would
be good.

However, I'd say, JS betters needs some sort of TCP blocks, which would
solve other similar cases (and which I'm pretty sure were discussed several
times couple of years ago). E.g. in Ruby that example would be much easier,
and that `@@reduced` would be just simple intuitive `return`.

Dmitry



 The only inkling of why this might be useful is an unsourced assertion
 that it's done in Clojure, for unknown reasons. The example code isn't very
 compelling either; something more real-world would be good there.
  --
 From: Lee Byron leeby...@fb.com
 Sent: ‎2015-‎02-‎23 00:58
 To: es-discuss@mozilla.org
 Subject: short-circuiting Array.prototype.reduce

  Hey all,

  I’d like to propose an addition to ES7 to add @@reduced as a way to
 short-circuit from Array.prototype.reduce.

  I’ve written up a polyfill and explanation here:

  https://github.com/leebyron/ecma-reduced

  I would love your feedback on this.

  Lee

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: @@toStringTag spoofing for null and undefined

2015-01-20 Thread Dmitry Soshnikov
A side note: while the `@toStringTag` topic is actively discussed and is
planned for the following meeting, I'd like to double-check the topic I
raised previously related to the `@toStringTag` and user-level classes: [1]
(basically provide default `@@toStringTag` being the class name), and what
Nicholas's use-case shows in his initial message in this thread.

[1] https://esdiscuss.org/topic/default-tostringtag-for-user-classes

Dmitry

On Mon, Jan 19, 2015 at 2:59 PM, Nicholas C. Zakas 
standa...@nczconsulting.com wrote:

 According to 19.1.3.6 Object.prototype.toString() [1], it's possible to do
 this:

 ```js
 function Foo(){}

 Foo.prototype[Symbol.toStringTag] = Null;

 Object.prototype.toString.call(new Foo());   // [object Null]
 ```

 It seems like `Null` and `Undefined` should be added to the step 17(b)
 list of exceptions to prevent spoofing of null and undefined values using
 this approach.

 I couldn't think of a reason why the current behavior would make sense,
 but if I'm off base, feel free to correct me. :)

 [1]: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-
 object.prototype.tostring

 --
 ___
 Nicholas C. Zakas
 http://www.nczonline.net

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Scoping of non-strict direct evals in parameter expressions

2014-12-03 Thread Dmitry Soshnikov
On Wed, Dec 3, 2014 at 2:09 PM, Allen Wirfs-Brock al...@wirfs-brock.com
wrote:

 See https://bugs.ecmascript.org/show_bug.cgi?id=3383

 The issue concerns things like this:

 don't use strict;
 var x=outer
 function f(a=eval( var x=1;  42),
  x=eval( console.log(can+(x!=1?'t:)+ see earlier
 eval binding}; 84)
  ) {
  console.log(x); // ? outer , 1, or  84?
 }
 f();


As it's now, it should be 84 seems, but with creation of `x` with the value
`1`, then printing `can see earlier eval binding`.


 In other words, for non-strict functions,  in what scope does should a
 direct eval that occurs in a parameter list expression context create its
 declarations.  Remember that formal parameters  have their own scope
 contour that is separate from the body scope (and the environment for the
 body scope doesn't even exist during parameter expression evaluation.  Also
 remember that legacy non-strict direct evals within functions create vars
 (and functions) in the variable scope of the function (which is the same as
 the body scope).

 I propose, that for scoping purposes, we treat such evals (parameter
 expression + non-strict + direct) as if they were strict evals. That means
 that all declarations created by the eval code are created in a new
 environment record that is discarded when the eval completes. Basically, it
 means that evals in parameter expression can't create bindings that are
 visible outside of the eval.


Yeah, since defaults params and the the whole intermediate params scope is
the whole new semantics, we can easily make this strict eval evaluation in
its isolated environment. Seems the easiest solution, so eventually the `x`
will be `outer`, and `can't see...`.

Dmitry



 Also, note that I'm not proposing that strict mode rules such as banning
 'with' be applied to the body of the eval.  I'm just talking about the
 declaration scoping rules.  This introduces a sort of micro-mode but the
 alternatives see less desirable.  They are 1) figure out a semantics of
 declarations injected into the function from parameter list evals; 2) force
 parameter list direct evals into full trict mode.  The first is hard,
 complex, and probably pointless; the second is still a sort of micro-mode,
 seems less aligned with the likely user intent, and I think will actually
 be harder to specify.

 Thoughts?

 Allen

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Default @@toStringTag for user classes

2014-12-02 Thread Dmitry Soshnikov
On Tue, Dec 2, 2014 at 9:56 AM, Andrea Giammarchi 
andrea.giammar...@gmail.com wrote:

 I think by `@@toStringTag` he meant the ability to define a `[[Class]]`
 name so that `{}.toString.call(generic)` would return such name instead of
 `Object` but I'm sure Dmitry will come back explaining and/or asking more.


Yeah, so basically current `O.p.toString` [1] in step 14 delegates to the
`@@toStringTag`. Which means user-classes have ability to ad-hoc the result
of using _default_ `toString` from `O.p`.

In a class users have to put it manually at the moment:

```
class Point {
  constructor(x, y) {
this._x = x;
this._y = y;
  }

  toString() {
return 'Point ' + this._x + ', ' + this._y + '';
  }

  [Symbol.toStringTag]() {
return 'Point';
  }
}

var p = new Point(10, 20);

console.log(p.toString()); // 'Point 10, 20'
console.log(({}).toString.call(p)); // '[object Point]'
```

Notice how the implementation defines its own `toString`, and at the same
time provides the ability to test the type tag with the `O.p.toString`.

So my proposal is to provide default implicit implementation of that
`Symbol.toStringTag` method (which is `@@toStringTag` in the spec).

Dmitry

[1]
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring



 On Tue, Dec 2, 2014 at 4:49 PM, Claude Pache claude.pa...@gmail.com
 wrote:


  Le 2 déc. 2014 à 08:46, Dmitry Soshnikov dmitry.soshni...@gmail.com
 a écrit :
 
  Hi,
 
  Probably worth providing a default implementation of the
 `@@toStringTag` when evaluating a class [1]. In this case users will be
 able to do:
 
  ```
  class Point { ... }
 
  var p = new Point(1, 2);
  console.log(p); // [object Point]
  ```

 You seem to imply that  `console.log(p)` will show the result of
 `p.toString()` in the console. But it is not the case for the majority of
 browsers.

 I've just tried:

 ```
 var Point = function() {}
 Point.prototype.toString = function() { return (this is an object of
 type Point) }
 console.log(new Point)
 ```

 Results are:

 Firefox: Object { }
 Chrome: Point{toString: function}
 Safari: Object
 IE: [object Object](this is an object of type Point)

 In particular, note that Chrome doesn't need the help of `.toString()` in
 order to log useful information.

 —Claude
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Default @@toStringTag for user classes

2014-12-02 Thread Dmitry Soshnikov
On Tue, Dec 2, 2014 at 5:12 PM, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:

 On Tue, Dec 2, 2014 at 9:56 AM, Andrea Giammarchi 
 andrea.giammar...@gmail.com wrote:

 I think by `@@toStringTag` he meant the ability to define a `[[Class]]`
 name so that `{}.toString.call(generic)` would return such name instead of
 `Object` but I'm sure Dmitry will come back explaining and/or asking more.


 Yeah, so basically current `O.p.toString` [1] in step 14 delegates to the
 `@@toStringTag`. Which means user-classes have ability to ad-hoc the result
 of using _default_ `toString` from `O.p`.

 In a class users have to put it manually at the moment:

 ```
 class Point {
   constructor(x, y) {
 this._x = x;
 this._y = y;
   }

   toString() {
 return 'Point ' + this._x + ', ' + this._y + '';
   }

   [Symbol.toStringTag]() {
 return 'Point';
   }


This one seems should be a getter actually based on the algorithm of
`O.p.toString`:

```
get [Symbol.toStringTag]() {
  return 'Point';
}
```

Dmitry


 }

 var p = new Point(10, 20);

 console.log(p.toString()); // 'Point 10, 20'
 console.log(({}).toString.call(p)); // '[object Point]'
 ```

 Notice how the implementation defines its own `toString`, and at the same
 time provides the ability to test the type tag with the `O.p.toString`.

 So my proposal is to provide default implicit implementation of that
 `Symbol.toStringTag` method (which is `@@toStringTag` in the spec).

 Dmitry

 [1]
 https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring



 On Tue, Dec 2, 2014 at 4:49 PM, Claude Pache claude.pa...@gmail.com
 wrote:


  Le 2 déc. 2014 à 08:46, Dmitry Soshnikov dmitry.soshni...@gmail.com
 a écrit :
 
  Hi,
 
  Probably worth providing a default implementation of the
 `@@toStringTag` when evaluating a class [1]. In this case users will be
 able to do:
 
  ```
  class Point { ... }
 
  var p = new Point(1, 2);
  console.log(p); // [object Point]
  ```

 You seem to imply that  `console.log(p)` will show the result of
 `p.toString()` in the console. But it is not the case for the majority of
 browsers.

 I've just tried:

 ```
 var Point = function() {}
 Point.prototype.toString = function() { return (this is an object of
 type Point) }
 console.log(new Point)
 ```

 Results are:

 Firefox: Object { }
 Chrome: Point{toString: function}
 Safari: Object
 IE: [object Object](this is an object of type Point)

 In particular, note that Chrome doesn't need the help of `.toString()`
 in order to log useful information.

 —Claude
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Default @@toStringTag for user classes

2014-12-01 Thread Dmitry Soshnikov
Hi,

Probably worth providing a default implementation of the `@@toStringTag`
when evaluating a class [1]. In this case users will be able to do:

```
class Point { ... }

var p = new Point(1, 2);
console.log(p); // [object Point]
```

The default implementation will be just (if the `className` is defined of
course):

```
proto[@@toStringTag] = function() {
  return className;
};
```

[1]
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Retrieving generator references

2014-11-22 Thread Dmitry Soshnikov
On Sat, Nov 22, 2014 at 8:03 PM, Brendan Eich bren...@mozilla.org wrote:

 Axel Rauschmayer wrote:


 A result of this mixing of concerns is that using `next()` to start a
 generator feels slightly off and that the argument of that first `next()`
 invocation is completely ignored.


 We've discussed a special generator head form to declare that name, but
 not for ES6. For now it's Pythonic, except we decided not to throw if the
 initial .next call passes a non-undefined value.


Yeah, in Python world (where initial JS generators came from) a technique
to prime a generator is often done via a decorator. JS doesn't have
decorators (yet), but it looks like:

```
// A helper decorator that primes the gen.
function coroutine(func) {
  return (...args) = {
var gen;
gen = func(...args);
gen.next();
return gen;
  };
}

// Actual gen.
let grep = coroutine(pattern = {
  let line;
  console.log('Looking for ' + pattern);
  while (true) {
line = yield;
if (line.indexOf(pattern !== -1)) {
  console.log('Found ' + pattern + ' in ' + line);
}
  }
  return true;
});

// Usage.
let g = grep('Coffee');

g.send('JavaScript');
g.send('CoffeeScript');
```

In Python it would be used as:

```
@coroutine
def grep(pattern):
  ...
```

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-11-19 Thread Dmitry Soshnikov
(For the history of this thread to refer to it later)

At the meeting it was decided not to go with `map` and `filter` sitting on
`Map.prototype`, but instead to use iterators in the way like:

```
map
  .entries() // returns an iterator
  .map((v, k, m) = { ... })
  .filter((v, k, m) = { ... })
  .collect(); // returns a new map after all transforms
```

The `forEach` method is the only which will still exist on `Map.prototype`,
and the committee agreed it's fine.

At the same time, the `forEach` can be called on iterator as well:

```
  map
.entries()
.map(...)
.forEach(...);
```

Dmitry

On Mon, Nov 17, 2014 at 1:09 PM, Brendan Eich bren...@mozilla.org wrote:

 Dmitry Soshnikov wrote:

 Is this something what is ready for discussion on a meeting (in
 particular, tomorrow's meeting)?


 You put something on the agenda, cool.

 https://github.com/tc39/agendas/blob/master/2014/11.md

 /be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-11-19 Thread Dmitry Soshnikov
(For the history of this thread to refer to it later)

At the meeting it was decided not to remove `keys()` and `entries()`, and
keep the `(value, againValue, set)` callback params signature.

The reasons:

- Consistency with maps and to reuse callbacks from arrays;
- Even if it may seem a wrong Set abstraction, it's too late to exclude
from ES6.

Dmitry

On Tue, Oct 14, 2014 at 1:19 PM, Erik Arvidsson erik.arvids...@gmail.com
wrote:

 Removing Set.prototype.entries and Set.prototype.keys might make sense.
 I'm not really sure why we added them. Probably for consistency.

 On Tue, Oct 14, 2014 at 2:42 PM, Axel Rauschmayer a...@rauschma.de
 wrote:

 Are we OK with this? Seems like removing `entries`, `keys` and providing
 own default `@@iterator` for `Set` which should be just `values()` would
 make it more sense from the abstraction usage perspective.


 W.r.t. your last suggestion: that’s how the spec does it. Anything else
 would definitely not have made sense.


 https://people.mozilla.org/~jorendorff/es6-draft.html#sec-set.prototype-@@iterator

 --
 Dr. Axel Rauschmayer
 a...@rauschma.de
 rauschma.de




 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss




 --
 erik

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-11-17 Thread Dmitry Soshnikov
Is this something what is ready for discussion on a meeting (in particular,
tomorrow's meeting)?

Regardless, whether the `map` and `set` will be directly on the
`Map.prototype` or on some generic `%CollectionPrototype%`, the user-level
API will stay the same, right? And will be used as:

```
myMap.map((v, k) = { ... });
```

I was just curious, is it already the time when it can be confirmed on a
meeting, that the API will likely be this (assuming we have `map.forEach`
already)? We'd like already to extend the `Map` and `Set` API (by extending
the ES6 base implementation) with several new methods, and start using them.

If this spec https://gist.github.com/DmitrySoshnikov/a218700746b2d7a7d2c8
is good enough to discuss it and can be confirmed, will it be a good time
on the following meeting? This PR for agenda wasn't merged for almost a
month: https://github.com/tc39/agendas/pull/53

If it can be confirmed already now, and no actual meeting discussion is
needed for this, I'm fine with this as well.

The only thing that may not confirm it, is using that new binding method
`::` operator and iter tools:

```
import {map} form 'iter-tools'

map::map(...);
```

But this as I understand is not even in early stage of a proposal (and
again, having dependency/correlation on `map.forEach` probably the `map`
and `filter` will nevertheless be used as just `map.map`).

P.S.: besides these two methods, maps and sets API is pretty basic at the
moment and doesn't have many every-day to use which are available in
other languages in these collections: like the most obvious intersect or
union operations for sets, etc. However, we can start with map and
filter yet ;)

Dmitry


On Wed, Oct 8, 2014 at 8:05 PM, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:

 On Wed, Oct 8, 2014 at 3:09 PM, Brendan Eich bren...@mozilla.org wrote:

 Dmitry Soshnikov wrote:


 The Collection protocol thus consists of at least .constructor,
 @@iterator, .set. (Is there a better way to clone? Don't want a
 new protocol where an old one will suffice!) This Collection
 protocol would include Map and maplikes but leaves out Set, Array,
 Object -- appropriately.


 As long as it can be generic enough for `Map`, `Set`


 Set methods include add, whereas Map has set. Set lacks a get method,
 whereas Map of course has one. So not the same protocol.


 I see, yeah, it's doable, and potentially they can be handled via abstract
 operations with checking kind of a collection (`IsSet`, `IsMap`), and
 setting needed entries (`AddEntry` would cover `set` for maps, and `add`
 for Sets), and `GetEntry` would return needed thing since sets are just
 backed by maps. However, this seems not a big win in terms of constant
 runtime checks for this, and probably having a separate algorithms are
 better (even if some parts are repeated).

 If you want to have just an explicit protocol/interface for MapLikes and
 SetLikes (i.e. with any explicit `set` method, and stuff which can be
 implemented at user-level by any object), it's possible. Although, this
 interface implementation can also be just replaced with sub-classing of the
 `Map`, and the same algorithm works. It's just a difference b/w duck-typing
 (the protocol, that any object may implement regardless its hierarchy), or
 the inheritance. Will think about it, and maybe will come up with a spec.

 Dmitry

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-14 Thread Dmitry Soshnikov
On Tue, Oct 14, 2014 at 11:42 AM, Axel Rauschmayer a...@rauschma.de wrote:

 Are we OK with this? Seems like removing `entries`, `keys` and providing
 own default `@@iterator` for `Set` which should be just `values()` would
 make it more sense from the abstraction usage perspective.


 W.r.t. your last suggestion: that’s how the spec does it. Anything else
 would definitely not have made sense.


 https://people.mozilla.org/~jorendorff/es6-draft.html#sec-set.prototype-@@iterator


So you're saying that `for-of` iterates only `values`, but `forEach` values
and keys (again values)?

```
var aSet = new Set([1, 2, 3]);

for (var v in aSet) {
  console.log(v); // 1, 2, 3
}
```

But

```
aSet.forEach((v, v1, theSet) = { ... });

```
Which is basically the same as:

```
for (var [v, v1] in aSet.entries()) {
  console.log(v, v1); // 1,1 2,2 3,3
}
```

That's said, if we remove the `entries` and `keys`, then the `v1` naturally
should (?) go away from the callback parameters as well, and in this case
we cannot reuse the callback functions from `Map`s or `Array`s.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-13 Thread Dmitry Soshnikov
On Mon, Oct 13, 2014 at 8:43 AM, Allen Wirfs-Brock al...@wirfs-brock.com
wrote:

 An old discussion.  See:

 https://esdiscuss.org/topic/set-and-map-additions-in-the-latest-draft
 https://esdiscuss.org/notes/2012-07-26 (section heading: Map and Set
 methods: conclusion)
 https://bugs.ecmascript.org/show_bug.cgi?id=591


OK, thanks for the info Allen. I guess, as long as it really was designed
this way (for reusable callbacks at first place), it's probably fine.
Though I still can predict confusions there.

Dmitry


 Allen


 On Oct 10, 2014, at 4:12 PM, Rick Waldron wrote:



 On Friday, October 10, 2014, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:

 Hi,

 (sorry I again probably too late, if the API is already locked, very
 likely it has been discussed and approved, please let me know)

 The API of `Set`s seems in inconvenient way exposes things that relates
 only to implementation details, but which doesn't make big sense at
 abstraction usage level.

 In particular, the `keys` and `entries` methods. I understand that `Set`s
 are just backed by `Map`s, and for simplicity of the specification reuse
 the same iteration algorithms (which by default calls `entries` for maps in
 `for-of`).

 But `keys` just doesn't make sense for sets, and the most inconvenient is
 callback function for `forEach` (and later for `map` and `filter` when they
 will be introduced). If devs want to analyze the set object itself, they
 have to repeat twice the value in parameters.

 ```
 (new Set([1,2,3])).forEach((value, againValue, theSet) = {
   // huh? againValue?
   ...
 });
 ```


 The designed to match A.p.forEach parameters to reduce refactoring
 hazards.

 Rick


 Are we OK with this? Seems like removing `entries`, `keys` and providing
 own default `@@iterator` for `Set` which should be just `values()` would
 make it more sense from the abstraction usage perspective.

 Dmitry

 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss



___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-13 Thread Dmitry Soshnikov
On Mon, Oct 13, 2014 at 3:22 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Allen Wirfs-Brock

  An old discussion.  See:

 These only address the `forEach` method though, and not the strange design
 of `entries()`, `values()`, and `keys()`. I guess a reusability argument
 could be made, but it seems strange to drive the API with the idea of
 wanting to reuse a Set in places people expect a Map.


Yeah, that's the purpose of an abstraction -- to hide implementation
details. `Set`s expose implementation details. Unless it's really much
easier to reuse the whole iteration protocol, it's _probably_ will be fine
(still again will be many confusions initially). But if it's easy to set
default `@@iterator` of `Sets` to just `values`, and kill the `keys()` and
`entries()`, it would be better. Although, once this is done, then the
`againValue` parameter won't make sense in the callback and will need to be
killed as well.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-13 Thread Dmitry Soshnikov
On Mon, Oct 13, 2014 at 4:25 PM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Monday, October 13, 2014, Domenic Denicola dome...@domenicdenicola.com
 wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Allen Wirfs-Brock

  An old discussion.  See:

 These only address the `forEach` method though, and not the strange
 design of `entries()`, `values()`, and `keys()`.


  Can you be more specific, strange is subjective and it's not clear what
 your referring to.


I think this may bring the thread to bikesheading :) In this case it's less
subjective, since `entries()` simply does not make (big, any?) sense for
sets from the abstraction perspective. As well as `keys()`. Only user-level
matters, implementations do not matter in API designs.

As long as it's already locked and was discussed in detail previously, I
think we can just close this one, I already warned about future confusions.
Reusing of a callback function could be considered as a good reason.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Set API

2014-10-10 Thread Dmitry Soshnikov
Hi,

(sorry I again probably too late, if the API is already locked, very likely
it has been discussed and approved, please let me know)

The API of `Set`s seems in inconvenient way exposes things that relates
only to implementation details, but which doesn't make big sense at
abstraction usage level.

In particular, the `keys` and `entries` methods. I understand that `Set`s
are just backed by `Map`s, and for simplicity of the specification reuse
the same iteration algorithms (which by default calls `entries` for maps in
`for-of`).

But `keys` just doesn't make sense for sets, and the most inconvenient is
callback function for `forEach` (and later for `map` and `filter` when they
will be introduced). If devs want to analyze the set object itself, they
have to repeat twice the value in parameters.

```
(new Set([1,2,3])).forEach((value, againValue, theSet) = {
  // huh? againValue?
  ...
});
```

Are we OK with this? Seems like removing `entries`, `keys` and providing
own default `@@iterator` for `Set` which should be just `values()` would
make it more sense from the abstraction usage perspective.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-10 Thread Dmitry Soshnikov
On Fri, Oct 10, 2014 at 4:09 PM, Brendan Eich bren...@mozilla.org wrote:

 Domenic Denicola wrote:

 That said, Set is shipping in every major browser so it's not going to
 get fixed now.


 Why do you say that?


Yeah, since the spec normally changes in some small parts, as e.g. with
recent change to `Array#last` and `Array#lastIndex` which do not skip holes
anymore (which is not the best from the compatibility with other similar
methods like `Array#map`, `Array#forEach`, etc). But as long as it's a new
policy, and why bother with holes if most of arrays are dense, not sparse
-- probably OK, I fixed my polyfills already. This is just for the word,
that browser change their implementations gradually anyway, once spec
changes.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-10 Thread Dmitry Soshnikov
On Fri, Oct 10, 2014 at 4:12 PM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Friday, October 10, 2014, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:

 Hi,

 (sorry I again probably too late, if the API is already locked, very
 likely it has been discussed and approved, please let me know)

 The API of `Set`s seems in inconvenient way exposes things that relates
 only to implementation details, but which doesn't make big sense at
 abstraction usage level.

 In particular, the `keys` and `entries` methods. I understand that `Set`s
 are just backed by `Map`s, and for simplicity of the specification reuse
 the same iteration algorithms (which by default calls `entries` for maps in
 `for-of`).

 But `keys` just doesn't make sense for sets, and the most inconvenient is
 callback function for `forEach` (and later for `map` and `filter` when they
 will be introduced). If devs want to analyze the set object itself, they
 have to repeat twice the value in parameters.

 ```
 (new Set([1,2,3])).forEach((value, againValue, theSet) = {
   // huh? againValue?
   ...
 });
 ```


 The designed to match A.p.forEach parameters to reduce refactoring
 hazards.

 Rick


Don't think I can agree with this. An abstraction should be intuitive and
predictable. For arrays and maps a key makes sense, for sets -- does not.
And refactoring hazards are secondary in this sense (though, can be
considered I agree).

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Set API

2014-10-10 Thread Dmitry Soshnikov
On Fri, Oct 10, 2014 at 4:13 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Fri, Oct 10, 2014 at 4:09 PM, Brendan Eich bren...@mozilla.org wrote:

 Domenic Denicola wrote:

 That said, Set is shipping in every major browser so it's not going to
 get fixed now.


 Why do you say that?


 Yeah, since the spec normally changes in some small parts, as e.g. with
 recent change to `Array#last` and `Array#lastIndex`


Err, sorry, `Array#find`, and `Array#findIndex` I meant of course (can't
edit posts).

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-08 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 4:08 PM, Claude Pache claude.pa...@gmail.com wrote:


 Le 7 oct. 2014 à 23:43, Dmitry Soshnikov dmitry.soshni...@gmail.com a
 écrit :

 On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. jackalm...@gmail.com
 wrote:

 On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  I see. Actually it doesn't work, your're correct, since
  `Array.prototype.map` does preserve the kind (at least in the latest
 draft).

 Hmm, per Rick's earlier email and
 
 https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
 ,
 Array#map (used by a subclass) doesn't preserve the subclass's type;
 it always returns an Array.

  And the `UInt32Array.from(...)` would be consuming a nodeList, not an
 array.
  Will the `nodeList.map(node = parseInt(node.value, 10));` by itself
  actually work then?

 If .map() is inherited from Array, and thus not type-preserving, yes,
 it'll work.


 Yes, it is preserving (probably was changed since that previous
 discussion), see (9) in
 http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
 Will a simple map to `node.value` on a `NodeList` work with the preserving
 `Array#map`?


 So, a `SortOfArray.from` (with a mapping) is finally less confusing than a  
 `SortOfArray#map`,
 for you don't have to look at the doc in order to determine the type of the
 result... :-p


Also related, and came on Twitter just not:
https://twitter.com/DmitrySoshnikov/status/519964146637737986

The mapping function from `Array.from` considers holes (from the new TC39
policy), but `Array#map` does not.

I guess this doc on `Array.from` from MDN [1] should be fixed then:

 More clearly, Array.from(obj, mapFn, thisArg) is the same as
Array.from(obj).map(mapFn, thisArg), except that it does not create an
intermediate array.

Since not only they are the same (as we confuse/substitute pre- and post-
mapping), but also the mapping function itself behaves differently.

[1]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-08 Thread Dmitry Soshnikov
On Wed, Oct 8, 2014 at 2:42 PM, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:

 On Tue, Oct 7, 2014 at 4:08 PM, Claude Pache claude.pa...@gmail.com
 wrote:


 Le 7 oct. 2014 à 23:43, Dmitry Soshnikov dmitry.soshni...@gmail.com a
 écrit :

 On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. jackalm...@gmail.com
 wrote:

 On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  I see. Actually it doesn't work, your're correct, since
  `Array.prototype.map` does preserve the kind (at least in the latest
 draft).

 Hmm, per Rick's earlier email and
 
 https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
 ,
 Array#map (used by a subclass) doesn't preserve the subclass's type;
 it always returns an Array.

  And the `UInt32Array.from(...)` would be consuming a nodeList, not an
 array.
  Will the `nodeList.map(node = parseInt(node.value, 10));` by itself
  actually work then?

 If .map() is inherited from Array, and thus not type-preserving, yes,
 it'll work.


 Yes, it is preserving (probably was changed since that previous
 discussion), see (9) in
 http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
 Will a simple map to `node.value` on a `NodeList` work with the preserving
 `Array#map`?


 So, a `SortOfArray.from` (with a mapping) is finally less confusing than
 a  `SortOfArray#map`, for you don't have to look at the doc in order to
 determine the type of the result... :-p


 Also related, and came on Twitter just not:
 https://twitter.com/DmitrySoshnikov/status/519964146637737986

 The mapping function from `Array.from` considers holes (from the new TC39
 policy), but `Array#map` does not.

 I guess this doc on `Array.from` from MDN [1] should be fixed then:

  More clearly, Array.from(obj, mapFn, thisArg) is the same as
 Array.from(obj).map(mapFn, thisArg), except that it does not create an
 intermediate array.

 Since not only they are the same (as we confuse/substitute pre- and
 post- mapping), but also the mapping function itself behaves differently.

 [1]
 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from


Never mind, as Rick and Allen clarified, they will produce the same arrays,
because of behavior of `Array.from` which as a result already has a hole
converted to explicit `undefined` value. Here is an example:
http://gyazo.com/4709305f3bde1c8ce0b02d2071a99e7f

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-08 Thread Dmitry Soshnikov
On Mon, Oct 6, 2014 at 9:37 AM, Brendan Eich bren...@mozilla.org wrote:

 Brendan Eich wrote:

 This meansMap.prototype.mapetc. -- or %ItereablePrototype%.map if not
 Array.prototype.map etc. -- are the eager collection-generic companions.


 Bear with me, trying to develop a half-thought. To say it with code:

 ```js
 Object.defineProperty(%IteratorPrototype%, 'map', {
 value: function (fun) {
 return function* (iter) {
 for (let [key, val] of iter) {
 yield fun(val, key);
 }
 }(this.clone());
 },
 configurable: true,
 enumerable: false,
 writable: true
 });
 ```

 Note the this.clone() call. This is novel, and required to avoid
 exhausting the receiver iterator.

 Rather than %IterablePrototype%, which is too generic a name (it does not
 imply a key/value map), we need something such as %MaplikePrototype% or
 %CollectionPrototype%:

 ```js
 Object.defineProperty(%CollectionPrototype%, 'map', {
 value: function (fun) {
 let result = new this.constructor();
 for (let [key, val] of this) {
 result.set(key, val);
 }
 return result;
 },
 configurable: true,
 enumerable: false,
 writable: true
 });
 ```

 The Collection protocol thus consists of at least .constructor,
 @@iterator, .set. (Is there a better way to clone? Don't want a new
 protocol where an old one will suffice!) This Collection protocol would
 include Map and maplikes but leaves out Set, Array, Object -- appropriately.


As long as it can be generic enough for `Map`, `Set` and .. (what else?) --
I actually like this one. Can try specifying it in a separate diff and will
get back to you.


 We could just use FP-style map, filter, etc. APIs, but as argued among
 TC39ers, OOP wins in JS: (a) it matches built-ins; (b) it composes left to
 right, not inside out.

 This argument implies a %CollectionPrototype% object full of
 protocol-generic methods, to avoid rewriting collection methods all over
 the place (wherever there is a maplike), or borrowing Map.prototype.*
 references by hand and monkeypatching them into maplike prototypes.


Yeah.


 Unless I'm mistaken, the OOP-ness also implies other stuff, like a way to
 clone an iterator.

 I hope this makes sense. Comments welcome.


Yep, thanks!

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-08 Thread Dmitry Soshnikov
On Wed, Oct 8, 2014 at 2:47 PM, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:


 On Wed, Oct 8, 2014 at 2:42 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 4:08 PM, Claude Pache claude.pa...@gmail.com
 wrote:


 Le 7 oct. 2014 à 23:43, Dmitry Soshnikov dmitry.soshni...@gmail.com a
 écrit :

 On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. jackalm...@gmail.com
 wrote:

 On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  I see. Actually it doesn't work, your're correct, since
  `Array.prototype.map` does preserve the kind (at least in the latest
 draft).

 Hmm, per Rick's earlier email and
 
 https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
 ,
 Array#map (used by a subclass) doesn't preserve the subclass's type;
 it always returns an Array.

  And the `UInt32Array.from(...)` would be consuming a nodeList, not an
 array.
  Will the `nodeList.map(node = parseInt(node.value, 10));` by itself
  actually work then?

 If .map() is inherited from Array, and thus not type-preserving, yes,
 it'll work.


 Yes, it is preserving (probably was changed since that previous
 discussion), see (9) in
 http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
 Will a simple map to `node.value` on a `NodeList` work with the preserving
 `Array#map`?


 So, a `SortOfArray.from` (with a mapping) is finally less confusing than
 a  `SortOfArray#map`, for you don't have to look at the doc in order to
 determine the type of the result... :-p


 Also related, and came on Twitter just not:
 https://twitter.com/DmitrySoshnikov/status/519964146637737986

 The mapping function from `Array.from` considers holes (from the new TC39
 policy), but `Array#map` does not.

 I guess this doc on `Array.from` from MDN [1] should be fixed then:

  More clearly, Array.from(obj, mapFn, thisArg) is the same as
 Array.from(obj).map(mapFn, thisArg), except that it does not create an
 intermediate array.

 Since not only they are the same (as we confuse/substitute pre- and
 post- mapping), but also the mapping function itself behaves differently.

 [1]
 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from


 Never mind, as Rick and Allen clarified, they will produce the same
 arrays, because of behavior of `Array.from` which as a result already has a
 hole converted to explicit `undefined` value. Here is an example:
 http://gyazo.com/4709305f3bde1c8ce0b02d2071a99e7f


However, these are two different semantics, although are both pre-mapping:

```
Array.from([1,,2].map(x=x*x)); // [1, 4]
Array.from([1,,2],x=x*x); // [1, NaN, 4]
```

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-08 Thread Dmitry Soshnikov
On Wed, Oct 8, 2014 at 3:09 PM, Brendan Eich bren...@mozilla.org wrote:

 Dmitry Soshnikov wrote:


 The Collection protocol thus consists of at least .constructor,
 @@iterator, .set. (Is there a better way to clone? Don't want a
 new protocol where an old one will suffice!) This Collection
 protocol would include Map and maplikes but leaves out Set, Array,
 Object -- appropriately.


 As long as it can be generic enough for `Map`, `Set`


 Set methods include add, whereas Map has set. Set lacks a get method,
 whereas Map of course has one. So not the same protocol.


I see, yeah, it's doable, and potentially they can be handled via abstract
operations with checking kind of a collection (`IsSet`, `IsMap`), and
setting needed entries (`AddEntry` would cover `set` for maps, and `add`
for Sets), and `GetEntry` would return needed thing since sets are just
backed by maps. However, this seems not a big win in terms of constant
runtime checks for this, and probably having a separate algorithms are
better (even if some parts are repeated).

If you want to have just an explicit protocol/interface for MapLikes and
SetLikes (i.e. with any explicit `set` method, and stuff which can be
implemented at user-level by any object), it's possible. Although, this
interface implementation can also be just replaced with sub-classing of the
`Map`, and the same algorithm works. It's just a difference b/w duck-typing
(the protocol, that any object may implement regardless its hierarchy), or
the inheritance. Will think about it, and maybe will come up with a spec.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 6:17 AM, C. Scott Ananian ecmascr...@cscott.net
wrote:

 On Tue, Oct 7, 2014 at 1:48 AM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron waldron.r...@gmail.com
 wrote:
  On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov
  dmitry.soshni...@gmail.com wrote:
  We're currently polyfilling `Array.from` in our codebase following the
  latest draft [1]. And I was actually surprised by the `mapfn` being
 involved
  into the algorithm.
  Have you tried es6-shim?
  Yeah, I'm aware of it, though, we have own versions for better
 performance,
  since may skip some internal checks, etc.

 (Speaking as an es6-shim maintainer) I'm always interested in
 benchmark results and performance patches.  Are the ES6-required
 checks really slowing you down?  I would think that most JITs and CPUs
 handle infrequently-taken branches pretty well these days.



The `es6-shim` is written well, though the performance is not the only
reason. We have own modules and polyfilling system, and don't polyfill
every single thing (just needed), so it's easier to write own.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Mon, Oct 6, 2014 at 10:48 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 Hi,

 We're currently polyfilling `Array.from` in our codebase following the
 latest draft [1]. And I was actually surprised by the `mapfn` being
 involved into the algorithm.


 Have you tried es6-shim?



 Yeah, I'm aware of it, though, we have own versions for better
 performance, since may skip some internal checks, etc.



 I mean, from the performance perspective it's probably .. ok-ish.. but
 from the API design perspective it feels like combining the actual
 transformation of an iterable (or of an array-like) with the mapping, is
 the too much of responsibility anti-pattern. Why not filter then as well?
 (or, as one of the comments on a diff review: I'm actually
 disappointed it won't do my laundry as well :P).

 It probably should be just:

 ```
 Array.from(...).map(mapfn);
 ```

 Unless I'm missing something, and there was a special reason to include
 the mapping.


 Yes:
 https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
 Any subclass of array will want to produce a list of its own kind, but
 .map returns an Array. This thread is also a dup of:
 https://mail.mozilla.org/pipermail/es-discuss/2013-June/031500.html


 I see. OK, thanks Rick, will re-read.


OK, have checked. And guess I still don't see a big issue, as long as the
`Array.prototype.map` preserves the kind (by delegating to `new
this.constructor(...)`).

That specific example like:

```
NodeList.form(['div', 'span'], nodeName =
document.createElement(nodeName));
```

arguing that the `NodeList` can't create elements from the strings doesn't
seems to me a good reason for introducing that anti-pattern, and it's
really should be rewritten as:

```
NodeList.form(['div', 'span'].map(nodeName =
document.createElement(nodeName)));
```

And other things are better be written:

```
ArrayKind.from(iterable).map(mapfn)
```

Am I still missing something?

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:46 AM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Dmitry Soshnikov

  Am I still missing something?

 Yes.

 ```js
 var uint16s = new Uint16Array([258]);
 var uint8s = Uint8Array.from(uint16s, x = x / 2);
 console.log(uint8s); // [129]
 ```

 ```js
 var uint16s = new Uint16Array([258]);
 var uint8s = Uint8Array.from(uint16s).map(x = x / 2);
 console.log(uint8s); // [1]
 ```


This seems the same issue as with the `NodeList`. The arguments for the
`from` should be anything that the constructor expects, if the `NodeList`
excepts a document node, it should be passed a document node, not a string.
I.e. the array should be mapped _before_ passing to the `from`.

```js
var uint16s = new Uint16Array([258]);
var uint8s = Uint8Array.from(uint16s.map(x = x / 2));
console.log(uint8s); // [129]
```

Is it?

Otherwise, we can back to the question why it doesn't do filter as well?

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache claude.pa...@gmail.com
wrote:




  Le 7 oct. 2014 à 20:36, Dmitry Soshnikov dmitry.soshni...@gmail.com a
 écrit :
 
  And other things are better be written:
 
  ```
  ArrayKind.from(iterable).map(mapfn)
  ```
 
  Am I still missing something?

 Yes:  `UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0))`


Still seems the same as `NodeList` issue:

```
UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0)));
```

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:01 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache claude.pa...@gmail.com
 wrote:




  Le 7 oct. 2014 à 20:36, Dmitry Soshnikov dmitry.soshni...@gmail.com
 a écrit :
 
  And other things are better be written:
 
  ```
  ArrayKind.from(iterable).map(mapfn)
  ```
 
  Am I still missing something?

 Yes:  `UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0))`


 Still seems the same as `NodeList` issue:

 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0)));
 ```


 And after you have fed the data the `UInt32Array` expects, you can
 post-map it as well:


 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0))).map(v = v *
 2);
 ```

 What's is wrong in here? We don't have too much of responsibility
 anti-pattern, explicitly separate the transformation form mapping, and
 explicitly say what the format of data a particular constructor expects
 (thus, mapping it before passing, as it should be).


And that's an iterable being passed to the from may not have the `map`
method doesn't seem to me a good reason either. Still this anti-pattern
feels worse.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 11:46 AM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Dmitry Soshnikov

  Am I still missing something?

 Yes.

 ```js
 var uint16s = new Uint16Array([258]);
 var uint8s = Uint8Array.from(uint16s, x = x / 2);
 console.log(uint8s); // [129]
 ```

 ```js
 var uint16s = new Uint16Array([258]);
 var uint8s = Uint8Array.from(uint16s).map(x = x / 2);
 console.log(uint8s); // [1]
 ```


Moreover, these two examples are semantically completely different. They
confuse and substitute the pre- and post- mapping. Clearly, it should be
pre-mapping here, and the second example is not even correct from this
perspective. And exactly manually pre-map it, is seems better, because that
`mapfn` on the API level can simply be confusing: what does it do -- maps
pre- or post?

And as mentioned above, after the correct list is constructed (with
possible pre-mapping), developers can also post-map it calling the
`Array.prototype.map` that still preserves the kind of the collection.

So I'd say, we should exclude the `mapfn` from `Array.from` in order to
keep the implementation (including polyfills) simpler and responsible for
only one things -- building a ArrayKind collection from another
collection or an iterable, consuming _correct_ data.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache claude.pa...@gmail.com
 wrote:




  Le 7 oct. 2014 à 20:36, Dmitry Soshnikov dmitry.soshni...@gmail.com
 a écrit :
 
  And other things are better be written:
 
  ```
  ArrayKind.from(iterable).map(mapfn)
  ```
 
  Am I still missing something?

 Yes:  `UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0))`


 Still seems the same as `NodeList` issue:

 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0)));
 ```


 And after you have fed the data the `UInt32Array` expects, you can
 post-map it as well:


 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0))).map(v = v *
 2);
 ```

 What's is wrong in here?


 That example will allocate 2 additional objects; the following version of
 the same operation will allocate _zero_ additional objects:

   UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0) * 2);


Exactly. And this is what I mentioned at the beginning: the performance
reasons shouldn't (never) overweight in good API design topics.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:25 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache claude.pa...@gmail.com
 wrote:




  Le 7 oct. 2014 à 20:36, Dmitry Soshnikov dmitry.soshni...@gmail.com
 a écrit :
 
  And other things are better be written:
 
  ```
  ArrayKind.from(iterable).map(mapfn)
  ```
 
  Am I still missing something?

 Yes:  `UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0))`


 Still seems the same as `NodeList` issue:

 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0)));
 ```


 And after you have fed the data the `UInt32Array` expects, you can
 post-map it as well:


 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0))).map(v = v *
 2);
 ```

 What's is wrong in here?


 That example will allocate 2 additional objects; the following version of
 the same operation will allocate _zero_ additional objects:

   UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0) * 2);


 Exactly. And this is what I mentioned at the beginning: the performance
 reasons shouldn't (never) overweight in good API design topics.


Since the next question will be: where is filter? It allows not allocating
stuff at all. However, we won't mention whether it's an anti-pattern or
not, since it goes without saying.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:27 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 12:25 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 12:22 PM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Tue, Oct 7, 2014 at 3:01 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:59 AM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 11:56 AM, Claude Pache claude.pa...@gmail.com
 wrote:




  Le 7 oct. 2014 à 20:36, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com a écrit :
 
  And other things are better be written:
 
  ```
  ArrayKind.from(iterable).map(mapfn)
  ```
 
  Am I still missing something?

 Yes:  `UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0))`


 Still seems the same as `NodeList` issue:

 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0)));
 ```


 And after you have fed the data the `UInt32Array` expects, you can
 post-map it as well:


 ```
 UInt32Array.from(['a', 'b', 'c].map(x = x.codePointAt(0))).map(v = v
 * 2);
 ```

 What's is wrong in here?


 That example will allocate 2 additional objects; the following version
 of the same operation will allocate _zero_ additional objects:

   UInt32Array.from(['a', 'b', 'c], x = x.codePointAt(0) * 2);


 Exactly. And this is what I mentioned at the beginning: the performance
 reasons shouldn't (never) overweight in good API design topics.


 Since the next question will be: where is filter? It allows not allocating
 stuff at all. However, we won't mention whether it's an anti-pattern or
 not, since it goes without saying.


I mean, yeah, we can accept and live with this -- aka, yeah why not, it's
convenient in place to pre-map, and good for cases when an iterable doesn't
have the `map`, and it's good for performance. But all the things from
above stands: it's confusing since doesn't explain whether it's pre- or
post- map, and takes too much at implementation.

Otherwise, I think it can be there, as long as it was approved already.
Worth though considering this in the future API designs: the performance
shouldn't drive the API.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 12:50 PM, Tab Atkins Jr. jackalm...@gmail.com
wrote:

 On Tue, Oct 7, 2014 at 12:32 PM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  I mean, yeah, we can accept and live with this -- aka, yeah why not, it's
  convenient in place to pre-map, and good for cases when an iterable
 doesn't
  have the `map`, and it's good for performance. But all the things from
 above
  stands: it's confusing since doesn't explain whether it's pre- or post-
 map,
  and takes too much at implementation.

 Alternately, you can just consider Foo.from to be the method version
 of a comprehension - you can feed it any iterable and transform the
 value arbitrarily before putting it into the new collection.  That
 does suggest that a filter argument would also be useful, as you've
 said


Yes, the list comprehensions is the thing that came to me in mind as well.

P.S @all: Also, I apologize I posted to many replies guys above. I wish I
could edit/combine them, but can't in the email. Hope it's not considered
as spam ;)

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 1:20 PM, Claude Pache claude.pa...@gmail.com wrote:


  Le 7 oct. 2014 à 21:32, Dmitry Soshnikov dmitry.soshni...@gmail.com a
 écrit :
 
  But all the things from above stands: it's confusing since doesn't
 explain whether it's pre- or post- map, and takes too much at
 implementation.

 My previous example could have been written as: `UInt32Array.from('abc', x
 = x.codePointAt(0))` (recalling that strings are iterable in ES6). My
 mapping is neither a pre-, nor a post-map. It's just a map which transforms
 a kind of value (a Unicode character) into another kind of value (a 32-bit
 integer).


This code example is a good justification of the an iterable doesn't have
own `map` method, but other than that, it's clearly pre-mapping, since
each element of the result is mapped before being set. The code is
semantically equivalent to:

```
UInt32Array.from('abc'.toArray().map(x = x.codePointAt(0));
```

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 1:45 PM, Bergi a.d.be...@web.de wrote:

 I think all of the above examples are trying to create a case such as

 | UInt32Array.from(nodelist, node = parseInt(node.value, 10) );

 where neither can nodes be stored in an Uint32Array nor integers be stored
 in a NodeList.


Not sure what you mean by nor integers be stored in a NodeList, but how
does your example differ from:

```
UInt32Array.from(nodeList.map(node = parseInt(node.value, 10)));
```

Anyhow, seems the only good reason (IMO) here is an iterable may not have
own `map` method, and we can live with that. And the broken and confusing
examples (when a post-map is substituted to the place of a clear pre-map)
do not help that much. Otherwise, I'd remove the `mapfn` from `Array.from`
(unless to turn it into a comprehensions API and accept the filter as well).

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 2:20 PM, Tab Atkins Jr. jackalm...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 2:11 PM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  On Tue, Oct 7, 2014 at 1:45 PM, Bergi a.d.be...@web.de wrote:
 
  I think all of the above examples are trying to create a case such as
 
  | UInt32Array.from(nodelist, node = parseInt(node.value, 10) );
 
  where neither can nodes be stored in an Uint32Array nor integers be
 stored
  in a NodeList.
 
 
  Not sure what you mean by nor integers be stored in a NodeList, but how
  does your example differ from:

 He meant that, assuming NodeList had a .map() that returned another
 NodeList (in general, assuming that .map() is type-preserving, which
 it's not currently), you wouldn't be able to easily do a map it
 first, then translate into the new collection - you'd have to
 explicitly translate it into a collection that can hold both UInt32
 and Node values, then map, then translate.

  ```
  UInt32Array.from(nodeList.map(node = parseInt(node.value, 10)));
  ```

 This works because .map() is not type-preserving, and automatically
 produces an Array (which can accept anything).


I see. Actually it doesn't work, your're correct, since
`Array.prototype.map` does preserve the kind (at least in the latest
draft). And the `UInt32Array.from(...)` would be consuming a nodeList, not
an array. Will the `nodeList.map(node = parseInt(node.value, 10));` by
itself actually work then?

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-07 Thread Dmitry Soshnikov
On Tue, Oct 7, 2014 at 2:35 PM, Tab Atkins Jr. jackalm...@gmail.com wrote:

 On Tue, Oct 7, 2014 at 2:26 PM, Dmitry Soshnikov
 dmitry.soshni...@gmail.com wrote:
  I see. Actually it doesn't work, your're correct, since
  `Array.prototype.map` does preserve the kind (at least in the latest
 draft).

 Hmm, per Rick's earlier email and
 
 https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
 ,
 Array#map (used by a subclass) doesn't preserve the subclass's type;
 it always returns an Array.

  And the `UInt32Array.from(...)` would be consuming a nodeList, not an
 array.
  Will the `nodeList.map(node = parseInt(node.value, 10));` by itself
  actually work then?

 If .map() is inherited from Array, and thus not type-preserving, yes,
 it'll work.


Yes, it is preserving (probably was changed since that previous
discussion), see (9) in
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.map.
Will a simple map to `node.value` on a `NodeList` work with the preserving
`Array#map`?

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-07 Thread Dmitry Soshnikov
On Sat, Oct 4, 2014 at 10:03 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Sat, Oct 4, 2014 at 5:58 PM, Domenic Denicola 
 dome...@domenicdenicola.com wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Domenic Denicola

  Unless I'm missing something (quite possible!), I would prefer not to
 add new methods to Map and Set when they could be added to
 %IteratorPrototype%.

 Yeah, I'm missing something. It's the difference in code between:

 ```js
 var newMap = oldMap.map(([k, v]) = [k + 1, v + 1]);
 ```

 versus

 ```js
 var newMap = new Map(oldMap.entries().map((([k, v]) = [k + 1, v + 1]);
 ```

 I think I still prefer avoiding every iterable subclass adding its own
 map/filter/etc. in favor of people using the compositional base primitives,
 but at least I see the argument now.


 We already have `Map#forEach`, and correlation with `Array#forEach -
 `Array#map` makes this constancy intuitive.

 The only thing which Rick mentioned, is that `Map#map` should probably
 return a transformed `[key, value]` pair, that allows updating the key as
 well. However, need to think about it, since as mentioned on the diff [1],
 usually people transform only values, and to force them always return an
 array may be annoying (the key is not transformed in this case), and less
 performant in terms useless array allocation.

 This case I'd probably make as `Map#mapWithKey`, however there other
 questions arise like, should the returned pair replace the existing, or
 create a new one, if the key is different?

 ```
 ({a = 10}).mapWithKey((k, v) = ['b', 20]); // {b = 20} or {a = 20, b
 = 20} ?
 ```

 But this is for further discussion.



I think it's definitely worth discussing the generic collection prototype,
however at the meantime, an updated version of the mapping function, here:
https://gist.github.com/DmitrySoshnikov/a218700746b2d7a7d2c8

- Moved the mapping to the abstract `MapTransform`
- Reused it for `Map#map` and `Map#mapEntries` (which updates the keys as
well)

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Array.from API

2014-10-06 Thread Dmitry Soshnikov
Hi,

We're currently polyfilling `Array.from` in our codebase following the
latest draft [1]. And I was actually surprised by the `mapfn` being
involved into the algorithm.

I mean, from the performance perspective it's probably .. ok-ish.. but from
the API design perspective it feels like combining the actual
transformation of an iterable (or of an array-like) with the mapping, is
the too much of responsibility anti-pattern. Why not filter then as well?
(or, as one of the comments on a diff review: I'm actually disappointed it
won't do my laundry as well :P).

It probably should be just:

```
Array.from(...).map(mapfn);
```

Unless I'm missing something, and there was a special reason to include the
mapping.

Dmitry

[1] https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.from API

2014-10-06 Thread Dmitry Soshnikov
On Mon, Oct 6, 2014 at 8:19 PM, Rick Waldron waldron.r...@gmail.com wrote:



 On Mon, Oct 6, 2014 at 10:59 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 Hi,

 We're currently polyfilling `Array.from` in our codebase following the
 latest draft [1]. And I was actually surprised by the `mapfn` being
 involved into the algorithm.


 Have you tried es6-shim?



Yeah, I'm aware of it, though, we have own versions for better performance,
since may skip some internal checks, etc.



 I mean, from the performance perspective it's probably .. ok-ish.. but
 from the API design perspective it feels like combining the actual
 transformation of an iterable (or of an array-like) with the mapping, is
 the too much of responsibility anti-pattern. Why not filter then as well?
 (or, as one of the comments on a diff review: I'm actually disappointed
 it won't do my laundry as well :P).

 It probably should be just:

 ```
 Array.from(...).map(mapfn);
 ```

 Unless I'm missing something, and there was a special reason to include
 the mapping.


 Yes:
 https://github.com/rwaldron/tc39-notes/blob/c61f48cea5f2339a1ec65ca89827c8cff170779b/es6/2013-01/jan-30.md#revising-the-array-subclassing-kind-issue
 Any subclass of array will want to produce a list of its own kind, but
 .map returns an Array. This thread is also a dup of:
 https://mail.mozilla.org/pipermail/es-discuss/2013-June/031500.html


I see. OK, thanks Rick, will re-read.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-05 Thread Dmitry Soshnikov
On Sat, Oct 4, 2014 at 10:03 PM, Dmitry Soshnikov 
dmitry.soshni...@gmail.com wrote:

 On Sat, Oct 4, 2014 at 5:58 PM, Domenic Denicola 
 dome...@domenicdenicola.com wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Domenic Denicola

  Unless I'm missing something (quite possible!), I would prefer not to
 add new methods to Map and Set when they could be added to
 %IteratorPrototype%.

 Yeah, I'm missing something. It's the difference in code between:

 ```js
 var newMap = oldMap.map(([k, v]) = [k + 1, v + 1]);
 ```

 versus

 ```js
 var newMap = new Map(oldMap.entries().map((([k, v]) = [k + 1, v + 1]);
 ```

 I think I still prefer avoiding every iterable subclass adding its own
 map/filter/etc. in favor of people using the compositional base primitives,
 but at least I see the argument now.


 We already have `Map#forEach`, and correlation with `Array#forEach -
 `Array#map` makes this constancy intuitive.

 The only thing which Rick mentioned, is that `Map#map` should probably
 return a transformed `[key, value]` pair, that allows updating the key as
 well. However, need to think about it, since as mentioned on the diff [1],
 usually people transform only values, and to force them always return an
 array may be annoying (the key is not transformed in this case), and less
 performant in terms useless array allocation.

 This case I'd probably make as `Map#mapWithKey`, however there other
 questions arise like, should the returned pair replace the existing, or
 create a new one, if the key is different?

 ```
 ({a = 10}).mapWithKey((k, v) = ['b', 20]); // {b = 20} or {a = 20, b
 = 20} ?
 ```


Whoops, nevermind actually, since we don't mutate the original map (the
`this`), but rather return a new one, it should always be just `{b = 20}`,
and `a` key is ignored in the transformed map.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-04 Thread Dmitry Soshnikov
On Sat, Oct 4, 2014 at 5:58 PM, Domenic Denicola 
dome...@domenicdenicola.com wrote:

 From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of
 Domenic Denicola

  Unless I'm missing something (quite possible!), I would prefer not to
 add new methods to Map and Set when they could be added to
 %IteratorPrototype%.

 Yeah, I'm missing something. It's the difference in code between:

 ```js
 var newMap = oldMap.map(([k, v]) = [k + 1, v + 1]);
 ```

 versus

 ```js
 var newMap = new Map(oldMap.entries().map((([k, v]) = [k + 1, v + 1]);
 ```

 I think I still prefer avoiding every iterable subclass adding its own
 map/filter/etc. in favor of people using the compositional base primitives,
 but at least I see the argument now.


We already have `Map#forEach`, and correlation with `Array#forEach -
`Array#map` makes this constancy intuitive.

The only thing which Rick mentioned, is that `Map#map` should probably
return a transformed `[key, value]` pair, that allows updating the key as
well. However, need to think about it, since as mentioned on the diff [1],
usually people transform only values, and to force them always return an
array may be annoying (the key is not transformed in this case), and less
performant in terms useless array allocation.

This case I'd probably make as `Map#mapWithKey`, however there other
questions arise like, should the returned pair replace the existing, or
create a new one, if the key is different?

```
({a = 10}).mapWithKey((k, v) = ['b', 20]); // {b = 20} or {a = 20, b =
20} ?
```

But this is for further discussion.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-02 Thread Dmitry Soshnikov
On Thu, Oct 2, 2014 at 12:00 PM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Wed, Oct 1, 2014 at 6:33 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Wed, Oct 1, 2014 at 1:26 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Wed, Oct 1, 2014 at 12:59 PM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Wed, Oct 1, 2014 at 3:51 PM, Jeremy Martin jmar...@gmail.com
 wrote:

 Not sure if this is sufficient motivation to accelerate the timeline



 It's not about motivation, it's about realistic time constraints.
 TC39 has already had to push out 6 months and that was not taken well by
 both the community and by Ecma. Further delay is not an option.


 Just out of curiosity: what's the realistic out of time issue here?
 Actually, I think having a ready and working algorithm draft on github gist
 will help discussing this faster and in realistic time frames (I've
 should've done before starting this thread; otherwise, these are too
 abstract time-stoppers for me -- unless you know specific big issues that
 will be hard to implement).



 OK, FWIW:

 - map: https://gist.github.com/DmitrySoshnikov/a218700746b2d7a7d2c8
 - filter: https://gist.github.com/DmitrySoshnikov/82b46f4674acee5cedc2


 Please make a PR to https://github.com/tc39/ecma262


Thanks, done. https://github.com/tc39/ecma262/pull/13

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Map: filter/map and more

2014-10-01 Thread Dmitry Soshnikov
Hi,

(Maps are awesome!)

1. Transforming iteration methods

We're currently polyfillying the `Map`, and got some questions form devs.
One of them is about transforming iteration methods, like `map` and
`filter`.

Unfortunately I missed that part of the spec when it was approved, so can
someone please remind/clarify -- was it an intended decision not to hap
Map#map, Map#filter? I can see only Map#forEach in the spec. Are maps
immutable? -- That's fine, the `map` and `filter` return a new map.

2. Declarative syntax

The other thing to note: currently maps a lack of a nice declarative
syntax. This one came from the use-case for maps for dynamic (computed)
property names.

Previously, we had to allocate an empty object, and then, in the imperative
style, append needed props:

```
var requestData = {};
requestData[Names.ID] = id;
requestData[Names.EMAIL] = email;
requestData.needsReload = true;
...
new Request(...)
  .setData(requestData)
  .send();
```

With computed properties of object initialisers it's much simpler and
convenient:

```
new Request(...)
  .setData({
[Names.ID]: id,
[Names.EMAIL]: email,
needsReload: true,
  })
  .send();
```

Then thing is: if we'd like to use maps for such use-case, it brings us
back to that inconvenient imperative style of assignments (even worse,
since you have to repeat that `.set(...)` constantly):

```
var requestData = new Map();
requestData.set(Names.ID, id);
requestData.set(Names.EMAIL, email);
requestData.set('needsReload', id);
...
```

Yes, we provide the iterable option for the constructor, and it can be
rewritten as (and this can even be inlined):

```
var requestData = new Map([
  [Names.ID, id],
  [Names.EMAIL, email],
  ['needsReload', id]
]);
```

However, obviously, it's too many arrays allocation for such a simple use
case.

Will it make sense having a nice declarative syntax like:

```
new Map({
  [Names.ID]: id,
  [Names.EMAIL]: email,
  needsReload: true,
})
```

It can even be done via a simple helper method that transforms this object
literal with computed props to the same iterable array of array, but this,
unfortunately, doesn't work with all cases like objects as keys.

I don't have the exact idea yet of how such a syntax can look like, but it
seems would be nice to have.

(unless, the use-case is not for maps, and we should use simple objects
here as was shown above)

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-01 Thread Dmitry Soshnikov
On Wed, Oct 1, 2014 at 11:57 AM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Wed, Oct 1, 2014 at 2:50 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 Hi,

 (Maps are awesome!)

 1. Transforming iteration methods

 We're currently polyfillying the `Map`, and got some questions form devs.
 One of them is about transforming iteration methods, like `map` and
 `filter`.

 Unfortunately I missed that part of the spec when it was approved, so can
 someone please remind/clarify -- was it an intended decision not to hap
 Map#map, Map#filter? I can see only Map#forEach in the spec. Are maps
 immutable? -- That's fine, the `map` and `filter` return a new map.



 Only with regard to time. I expect there will be substantial additions to
 Map and Set in ES7 (as long as the work is done, of course).


Hm, sounds like two copy-pasting algorithms from the same `Array#map`,
`Array#filter`, or just tweaking the `Map#forEach` (I might be missing
something).






 2. Declarative syntax

 The other thing to note: currently maps a lack of a nice declarative
 syntax. This one came from the use-case for maps for dynamic (computed)
 property names.


 Previously, we had to allocate an empty object, and then, in the
 imperative style, append needed props:

 ```
 var requestData = {};
 requestData[Names.ID] = id;
 requestData[Names.EMAIL] = email;
 requestData.needsReload = true;
 ...
 new Request(...)
   .setData(requestData)
   .send();
 ```

 With computed properties of object initialisers it's much simpler and
 convenient:

 ```
 new Request(...)
   .setData({
 [Names.ID]: id,
 [Names.EMAIL]: email,
 needsReload: true,
   })
   .send();
 ```

 Then thing is: if we'd like to use maps for such use-case, it brings us
 back to that inconvenient imperative style of assignments (even worse,
 since you have to repeat that `.set(...)` constantly):

 ```
 var requestData = new Map();
 requestData.set(Names.ID, id);
 requestData.set(Names.EMAIL, email);
 requestData.set('needsReload', id);
 ...
 ```

 Yes, we provide the iterable option for the constructor, and it can be
 rewritten as (and this can even be inlined):

 ```
 var requestData = new Map([
   [Names.ID, id],
   [Names.EMAIL, email],
   ['needsReload', id]
 ]);
 ```

 However, obviously, it's too many arrays allocation for such a simple use
 case.

 Will it make sense having a nice declarative syntax like:

 ```
 new Map({
   [Names.ID]: id,
   [Names.EMAIL]: email,
   needsReload: true,
 })
 ```


 This doesn't work because Maps allow objects as keys.


Yes, I said it myself above. That's the thing -- I'd like to thing about
some special syntax maybe. Don't know yet, probably map as a construct for
declarative cases like:

```
// Declarative
Map {
  [foo]: 1,
  bar: 2,
}

// Imperative (via constructor)
new Map([ // brrr..
  [foo, 1],
  ['bar', 2]
])
```

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-01 Thread Dmitry Soshnikov
On Wed, Oct 1, 2014 at 12:59 PM, Rick Waldron waldron.r...@gmail.com
wrote:



 On Wed, Oct 1, 2014 at 3:51 PM, Jeremy Martin jmar...@gmail.com wrote:

 Not sure if this is sufficient motivation to accelerate the timeline



 It's not about motivation, it's about realistic time constraints. TC39
 has already had to push out 6 months and that was not taken well by both
 the community and by Ecma. Further delay is not an option.


Just out of curiosity: what's the realistic out of time issue here?
Actually, I think having a ready and working algorithm draft on github gist
will help discussing this faster and in realistic time frames (I've
should've done before starting this thread; otherwise, these are too
abstract time-stoppers for me -- unless you know specific big issues that
will be hard to implement).




 for adding suitable parallels from Array.prototype, but it may be worth
 recalling what developers did last time there were obvious gaps in what a
 native prototype provided.  Array#contains, anyone?


 As a community we'll simply have to reject the use of code that directly
 modifies built-ins. This is also not a very strong argument in the ES6
 world where built-ins can be subclassed.


Actually the case with borken `Array#contains` which is so actively
discussed, is a good example. I think very likely `Map#map`, and
`Map#filter` will be added manually if not in ES6.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-01 Thread Dmitry Soshnikov
On Wed, Oct 1, 2014 at 1:26 PM, Dmitry Soshnikov dmitry.soshni...@gmail.com
 wrote:

 On Wed, Oct 1, 2014 at 12:59 PM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Wed, Oct 1, 2014 at 3:51 PM, Jeremy Martin jmar...@gmail.com wrote:

 Not sure if this is sufficient motivation to accelerate the timeline



 It's not about motivation, it's about realistic time constraints. TC39
 has already had to push out 6 months and that was not taken well by both
 the community and by Ecma. Further delay is not an option.


 Just out of curiosity: what's the realistic out of time issue here?
 Actually, I think having a ready and working algorithm draft on github gist
 will help discussing this faster and in realistic time frames (I've
 should've done before starting this thread; otherwise, these are too
 abstract time-stoppers for me -- unless you know specific big issues that
 will be hard to implement).



OK, FWIW:

- map: https://gist.github.com/DmitrySoshnikov/a218700746b2d7a7d2c8
- filter: https://gist.github.com/DmitrySoshnikov/82b46f4674acee5cedc2

Does it look like a vital algorithm? And if no one sees big/any issue with,
can it potentially be considered for inclusion? I'm not gonna push it of
course taking into account higher-pri things, however, if it seems to
everyone trivial -- why not.

(Otherwise, at least it can be a source for monkey-patching the
`Map.prototype` if it's only for ES7).

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-01 Thread Dmitry Soshnikov
On Wed, Oct 1, 2014 at 12:28 PM, Axel Rauschmayer a...@rauschma.de wrote:


 Then thing is: if we'd like to use maps for such use-case, it brings us
 back to that inconvenient imperative style of assignments (even worse,
 since you have to repeat that `.set(...)` constantly):

 ```
 var requestData = new Map();
 requestData.set(Names.ID, id);
 requestData.set(Names.EMAIL, email);
 requestData.set('needsReload', id);
 ...
 ```


 Note that you can chain:

 ```js
 var requestData = new Map()
 .set(Names.ID, id)
 .set(Names.EMAIL, email)
 .set('needsReload', id);
 ```

 Not too bad, IMO.


Not ideal either. Usually langs provide nice declarative syntax for such
things. E.g. we have[1] the same in the HACK language, and use it well
everyday when need a map.

But this part is of course not for ES6, hope ES7-ish.

[1] http://docs.hhvm.com/manual/en/hack.collections.map.php
Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-01 Thread Dmitry Soshnikov
On Wed, Oct 1, 2014 at 1:38 PM, Rick Waldron waldron.r...@gmail.com wrote:



 On Wed, Oct 1, 2014 at 4:26 PM, Dmitry Soshnikov 
 dmitry.soshni...@gmail.com wrote:

 On Wed, Oct 1, 2014 at 12:59 PM, Rick Waldron waldron.r...@gmail.com
 wrote:



 On Wed, Oct 1, 2014 at 3:51 PM, Jeremy Martin jmar...@gmail.com wrote:

 Not sure if this is sufficient motivation to accelerate the timeline



 It's not about motivation, it's about realistic time constraints. TC39
 has already had to push out 6 months and that was not taken well by both
 the community and by Ecma. Further delay is not an option.


 Just out of curiosity: what's the realistic out of time issue here?
 Actually, I think having a ready and working algorithm draft on github gist
 will help discussing this faster and in realistic time frames (I've
 should've done before starting this thread; otherwise, these are too
 abstract time-stoppers for me -- unless you know specific big issues that
 will be hard to implement).


 If this was really pressing, why wasn't it on any meeting agendas in the
 last year?


I'm sorry, as mentioned at the beginning of this thread, I unfortunately
missed this part of the spec when the decisions were made. And since we
just recently started to polyfill the `Map` in our codebase following the
spec, I was surprised that neither `map`, nor `filter` are actually in the
spec. I thought there were some real big issues, and wanted to clarify
them. If it's only out of time, I'd of course propose it for the agenda.


 The spec must be essentially finished by the next meeting (the last
 meeting in 2014). Finalizing the Loader details, super class instantiation
 (you might recall that was an issue recently), RegExp work in Annex B (may
 require lexical grammar changes), revising, reviewing, etc. (I know there
 is a lot more here)... All of this takes precedence over API surface
 additions, whether complete or not. Additionally, the committee is trying
 establish a new process for all new features. Domenic could've tried to
 push Array.prototype.contains into ES6, but he's following the process.
 https://github.com/tc39/ecma262


Yeah, absolutely agree that these are higher-pri.










 for adding suitable parallels from Array.prototype, but it may be worth
 recalling what developers did last time there were obvious gaps in what a
 native prototype provided.  Array#contains, anyone?


 As a community we'll simply have to reject the use of code that directly
 modifies built-ins. This is also not a very strong argument in the ES6
 world where built-ins can be subclassed.


 Actually the case with borken `Array#contains` which is so actively
 discussed, is a good example. I think very likely `Map#map`, and
 `Map#filter` will be added manually if not in ES6.


 See my response, I doubt that a one year wait until ES7 will really ruin
 the chances for map and filter methods. In the meantime, write the spec,
 get it added to https://github.com/tc39/ecma262 and enforce the semantics
 on all userland implementations. Time will fly, I promise.


Sure, at first glance the algorithms are trivial enough as posted above.

Dmitry
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


  1   2   3   >