Re: Array.prototype.remove(item)

2018-10-10 Thread Sanford Whiteman
> You need to cite your sources

> hi Sandy, sure hear are 2 sources:

So you believe these 2 patches prove "most of the tech debt" across
all JavaScript product development is due to this factor.

Huh.

Well, to each their own as far as how "proof" works. I prefer the
classical definition. You know, the one where you use the actual
population you're generalizing about.


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


RE: Array.prototype.remove(item)

2018-10-10 Thread Ron Buckton
That depends entirely on what the return value means. Returning Boolean from 
`add` doesn’t mean, “does the value now exist in the set”, but rather means 
“was the set modified as a result of this operation”.

To avoid any possible performance cost for calling `has` before `add`, I 
usually have to do something like:

```
function setAdd(set, value) {
  const size = set.size;
  set.add(value);
  return size !== set.size;
}
```

From: es-discuss  On Behalf Of Jordan Harband
Sent: Wednesday, October 10, 2018 7:19 PM
To: jollee...@outlook.com
Cc: es-discuss 
Subject: Re: Array.prototype.remove(item)

Man: `add` doesn't need to return a boolean, because it always results in the 
item being in the collection after the fact. You could subclass Set, and make 
`.add` do that, though, if you like! Alternatively, you could use `.has` prior 
to calling `.add`, to get your boolean value.

On Wed, Oct 10, 2018 at 1:01 AM Man Hoang 
mailto:jollee...@outlook.com>> wrote:
The problem with `Set` is that its `add` method returns `this` instead of 
`boolean`. If `Set.prototype.add` returned `boolean`, I would have used `Set`.

That’s why in the `select` method of my sample code, I use a custom defined 
method named `pushIfAbsent`. The actual type of `_values` is not `Array` but a 
subclass of `Array`.
``` js
export class MyArray extends Array {
/**
 * Adds [item] to the end of this array if it's not already in this array.
 *
 * Returns `true` is [item] was added, `false` otherwise.
 */
pushIfAbsent(item: E): boolean {
if (!this.includes(item)) {
this.push(item);
return true;
}
return false;
}

/**
 * Removes the first occurrence of [item] from this array.
 *
 * Returns `true` if [item] was in this array, `false` otherwise.
 */
remove(item: E): boolean {
const i = this.indexOf(item);
if (i >= 0) {
this.splice(i, 1);
return true;
}
return false;
}
}
```
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Ron Buckton
I have seen this in other languages as `getOrCreate(key, valueFactory)`. 
Dictionaries in .NET have a `TryGetValue(key, out value)` method that returns a 
boolean and has an ‘out’ parameter used to assign the value if it exists. The 
performance issue regarding keys is one of my common concerns with 
`Set.prototype.add`, as it would have been significantly more useful for `add` 
to return a Boolean indicating whether the value was added (true), or was 
already present (false).

At the end of the day, I usually just end up defining `mapGetOrCreate(map, key, 
valueFactory)` and `setAdd(set, value)` utility functions that I end up using.

From: es-discuss  On Behalf Of Andrea Giammarchi
Sent: Wednesday, October 10, 2018 9:30 PM
To: Jordan Harband 
Cc: es-discuss@mozilla.org
Subject: Re: Proposal: Add Map.prototype.putIfAbsent

No. The raised concern has been common among developers and the main issue is 
that `set` returns itself which is the least useful pattern.

Your suggestion would make sense if `const value = map.has(key) ? map.get(key) 
: map.set(key, createValue())` instead ES went for chain ability and yet, to 
date, I have to see a single usage of `map.set(a, 1).set(b, 2)` in the wild.

On top of that, needing to `.has` and then `.get` is a performance shenanigan 
many would likely avoid at all costs 'cause AFAIK in no engine `.has(key)` 
temporarily retains last searched key to boost up the immediate `.get(key)` 
later on so having a `.putIfAbsent(key, createValue())` that returns either the 
found or the created value is a clear win.



On Thu, Oct 11, 2018 at 6:20 AM Jordan Harband 
mailto:ljh...@gmail.com>> wrote:
Thanks, your correction explains what the benefit would be (the awkward need to 
cache the value). However this seems simpler to me: `if (!map.has(key)) { 
map.set(key, getValue()); } const value = map.get(key);`

On Wed, Oct 10, 2018 at 9:07 PM Isiah Meadows 
mailto:isiahmead...@gmail.com>> wrote:
I presume you mean this?

```js
// Proposed
map.putIfAbsent(key, init)

// How you do it now
let value
if (map.has(key)) {
value = map.get(key)
} else {
map.set(key, value = init())
}
```

BTW, I'd like to see this make it myself, just slightly different:

- How you call it: `map.getOrPut(key, init, thisValue=undefined)`
- How `init` is called: `init.call(thisValue, key, map)`

This pattern is incredibly common for caching. It'd be nice if I didn't have to 
repeat myself so much with it. I would be more willing to stuff it in a utility 
function if it weren't for the fact the use cases often entail 
performance-sensitive paths, and engines aren't reliable enough in my 
experience with inlining closures passed to non-builtins.

On Wed, Oct 10, 2018 at 22:54 Jordan Harband 
mailto:ljh...@gmail.com>> wrote:
It seems like your proposed `const value = map.putIfAbsent(key, 
getExpensiveValue);` is achievable already with `const value = map.has(key) ? 
map.get(key) : map.set(getExpensiveValue());` - am I understanding your 
suggestion correctly?

On Wed, Oct 10, 2018 at 12:46 AM Man Hoang 
mailto:jollee...@outlook.com>> wrote:
Consider the following function
``` js
/**
* Parses the locale sensitive string [value] into a number.
*/
export function parseNumber(
value: string,
locale: string = navigator.language
): number {
let decimalSeparator = decimalSeparators.get(locale);
if (!decimalSeparator) {
decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];
decimalSeparators.set(locale, decimalSeparator);
}

let cleanRegExp = regExps.get(decimalSeparator);
if (!cleanRegExp) {
cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');
regExps.set(decimalSeparator, cleanRegExp);
}

value = value
.replace(cleanRegExp, '')
.replace(decimalSeparator, '.');

return parseFloat(value);
}

const decimalSeparators = new Map();
const regExps = new Map();
```

This function can be simplified quite a bit as follows
``` js
export function parseNumber(
value: string,
locale: string = navigator.language
): number {
const decimalSeparator = decimalSeparators.putIfAbsent(
locale, () => Intl.NumberFormat(locale).format(1.1)[1]);

const cleanRegExp = regExps.putIfAbsent(
decimalSeparator, () => new RegExp(`[^-+0-9${decimalSeparator}]`, 'g'));

value = value
.replace(cleanRegExp, '')
.replace(decimalSeparator, '.');

return parseFloat(value);
}
```
if `Map` has the following instance method
``` js
export class Map {
/**
 * Look up the value of [key], or add a new value if it isn't there.
 *
 * Returns the value associated to [key], if there is one.
 * Otherwise calls [ifAbsent] to get a new value, associates [key] to
 * that value, and then returns the new value.
 */
putIfAbsent(key: K, ifAbsent: () => V): V {
let v = this.get(key);
if (v === undefined) {
v = ifAbsent();
this.set(key, v);
  

Re: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Isiah Meadows
It's slghtly simpler in terms of lines of code, but it's still more awkward
than it should be for that kind of thing.

On Thu, Oct 11, 2018 at 00:20 Jordan Harband  wrote:

> Thanks, your correction explains what the benefit would be (the awkward
> need to cache the value). However this seems simpler to me: `if
> (!map.has(key)) { map.set(key, getValue()); } const value = map.get(key);`
>
> On Wed, Oct 10, 2018 at 9:07 PM Isiah Meadows 
> wrote:
>
>> I presume you mean this?
>>
>> ```js
>> // Proposed
>> map.putIfAbsent(key, init)
>>
>> // How you do it now
>> let value
>> if (map.has(key)) {
>> value = map.get(key)
>> } else {
>> map.set(key, value = init())
>> }
>> ```
>>
>> BTW, I'd like to see this make it myself, just slightly different:
>>
>> - How you call it: `map.getOrPut(key, init, thisValue=undefined)`
>> - How `init` is called: `init.call(thisValue, key, map)`
>>
>> This pattern is incredibly common for caching. It'd be nice if I didn't
>> have to repeat myself so much with it. I would be more willing to stuff it
>> in a utility function if it weren't for the fact the use cases often entail
>> performance-sensitive paths, and engines aren't reliable enough in my
>> experience with inlining closures passed to non-builtins.
>>
>> On Wed, Oct 10, 2018 at 22:54 Jordan Harband  wrote:
>>
>>> It seems like your proposed `const value = map.putIfAbsent(key,
>>> getExpensiveValue);` is achievable already with `const value = map.has(key)
>>> ? map.get(key) : map.set(getExpensiveValue());` - am I understanding your
>>> suggestion correctly?
>>>
>>> On Wed, Oct 10, 2018 at 12:46 AM Man Hoang 
>>> wrote:
>>>
 Consider the following function

 ``` js

 /**

 * Parses the locale sensitive string [value] into a number.

 */

 export function parseNumber(

 value: string,

 locale: string = navigator.language

 ): number {

 let decimalSeparator = decimalSeparators.get(locale);

 if (!decimalSeparator) {

 decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];

 decimalSeparators.set(locale, decimalSeparator);

 }



 let cleanRegExp = regExps.get(decimalSeparator);

 if (!cleanRegExp) {

 cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');

 regExps.set(decimalSeparator, cleanRegExp);

 }



 value = value

 .replace(cleanRegExp, '')

 .replace(decimalSeparator, '.');



 return parseFloat(value);

 }



 const decimalSeparators = new Map();

 const regExps = new Map();

 ```



 This function can be simplified quite a bit as follows

 ``` js

 export function parseNumber(

 value: string,

 locale: string = navigator.language

 ): number {

 const decimalSeparator = decimalSeparators.putIfAbsent(

 locale, () => Intl.NumberFormat(locale).format(1.1)[1]);



 const cleanRegExp = regExps.putIfAbsent(

 decimalSeparator, () => new
 RegExp(`[^-+0-9${decimalSeparator}]`, 'g'));



 value = value

 .replace(cleanRegExp, '')

 .replace(decimalSeparator, '.');



 return parseFloat(value);

 }

 ```

 if `Map` has the following instance method

 ``` js

 export class Map {

 /**

  * Look up the value of [key], or add a new value if it isn't there.

  *

  * Returns the value associated to [key], if there is one.

  * Otherwise calls [ifAbsent] to get a new value, associates [key]
 to

  * that value, and then returns the new value.

  */

 putIfAbsent(key: K, ifAbsent: () => V): V {

 let v = this.get(key);

 if (v === undefined) {

 v = ifAbsent();

 this.set(key, v);

 }

 return v;

 }

 }

 ```



 Java's Map has a `putIfAbsent` method, which accepts a value rather
 than a function for the second parameter. This is not ideal as computing
 the value may be expensive. A function would allow the value to be computed
 lazily.



 References

 - [Dart] [Map.putIfAbsent](
 https://api.dartlang.org/stable/2.0.0/dart-core/Map/putIfAbsent.html)

 - [Java] [Map.putIfAbsent](
 https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#putIfAbsent-K-V-
 )
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

>>> __

Re: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Andrea Giammarchi
No. The raised concern has been common among developers and the main issue
is that `set` returns itself which is the least useful pattern.

Your suggestion would make sense if `const value = map.has(key) ?
map.get(key) : map.set(key, createValue())` instead ES went for chain
ability and yet, to date, I have to see a single usage of `map.set(a,
1).set(b, 2)` in the wild.

On top of that, needing to `.has` and then `.get` is a performance
shenanigan many would likely avoid at all costs 'cause AFAIK in no engine
`.has(key)` temporarily retains last searched key to boost up the immediate
`.get(key)` later on so having a `.putIfAbsent(key, createValue())` that
returns either the found or the created value is a clear win.



On Thu, Oct 11, 2018 at 6:20 AM Jordan Harband  wrote:

> Thanks, your correction explains what the benefit would be (the awkward
> need to cache the value). However this seems simpler to me: `if
> (!map.has(key)) { map.set(key, getValue()); } const value = map.get(key);`
>
> On Wed, Oct 10, 2018 at 9:07 PM Isiah Meadows 
> wrote:
>
>> I presume you mean this?
>>
>> ```js
>> // Proposed
>> map.putIfAbsent(key, init)
>>
>> // How you do it now
>> let value
>> if (map.has(key)) {
>> value = map.get(key)
>> } else {
>> map.set(key, value = init())
>> }
>> ```
>>
>> BTW, I'd like to see this make it myself, just slightly different:
>>
>> - How you call it: `map.getOrPut(key, init, thisValue=undefined)`
>> - How `init` is called: `init.call(thisValue, key, map)`
>>
>> This pattern is incredibly common for caching. It'd be nice if I didn't
>> have to repeat myself so much with it. I would be more willing to stuff it
>> in a utility function if it weren't for the fact the use cases often entail
>> performance-sensitive paths, and engines aren't reliable enough in my
>> experience with inlining closures passed to non-builtins.
>>
>> On Wed, Oct 10, 2018 at 22:54 Jordan Harband  wrote:
>>
>>> It seems like your proposed `const value = map.putIfAbsent(key,
>>> getExpensiveValue);` is achievable already with `const value = map.has(key)
>>> ? map.get(key) : map.set(getExpensiveValue());` - am I understanding your
>>> suggestion correctly?
>>>
>>> On Wed, Oct 10, 2018 at 12:46 AM Man Hoang 
>>> wrote:
>>>
 Consider the following function

 ``` js

 /**

 * Parses the locale sensitive string [value] into a number.

 */

 export function parseNumber(

 value: string,

 locale: string = navigator.language

 ): number {

 let decimalSeparator = decimalSeparators.get(locale);

 if (!decimalSeparator) {

 decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];

 decimalSeparators.set(locale, decimalSeparator);

 }



 let cleanRegExp = regExps.get(decimalSeparator);

 if (!cleanRegExp) {

 cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');

 regExps.set(decimalSeparator, cleanRegExp);

 }



 value = value

 .replace(cleanRegExp, '')

 .replace(decimalSeparator, '.');



 return parseFloat(value);

 }



 const decimalSeparators = new Map();

 const regExps = new Map();

 ```



 This function can be simplified quite a bit as follows

 ``` js

 export function parseNumber(

 value: string,

 locale: string = navigator.language

 ): number {

 const decimalSeparator = decimalSeparators.putIfAbsent(

 locale, () => Intl.NumberFormat(locale).format(1.1)[1]);



 const cleanRegExp = regExps.putIfAbsent(

 decimalSeparator, () => new
 RegExp(`[^-+0-9${decimalSeparator}]`, 'g'));



 value = value

 .replace(cleanRegExp, '')

 .replace(decimalSeparator, '.');



 return parseFloat(value);

 }

 ```

 if `Map` has the following instance method

 ``` js

 export class Map {

 /**

  * Look up the value of [key], or add a new value if it isn't there.

  *

  * Returns the value associated to [key], if there is one.

  * Otherwise calls [ifAbsent] to get a new value, associates [key]
 to

  * that value, and then returns the new value.

  */

 putIfAbsent(key: K, ifAbsent: () => V): V {

 let v = this.get(key);

 if (v === undefined) {

 v = ifAbsent();

 this.set(key, v);

 }

 return v;

 }

 }

 ```



 Java's Map has a `putIfAbsent` method, which accepts a value rather
 than a fun

Re: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Jordan Harband
Thanks, your correction explains what the benefit would be (the awkward
need to cache the value). However this seems simpler to me: `if
(!map.has(key)) { map.set(key, getValue()); } const value = map.get(key);`

On Wed, Oct 10, 2018 at 9:07 PM Isiah Meadows 
wrote:

> I presume you mean this?
>
> ```js
> // Proposed
> map.putIfAbsent(key, init)
>
> // How you do it now
> let value
> if (map.has(key)) {
> value = map.get(key)
> } else {
> map.set(key, value = init())
> }
> ```
>
> BTW, I'd like to see this make it myself, just slightly different:
>
> - How you call it: `map.getOrPut(key, init, thisValue=undefined)`
> - How `init` is called: `init.call(thisValue, key, map)`
>
> This pattern is incredibly common for caching. It'd be nice if I didn't
> have to repeat myself so much with it. I would be more willing to stuff it
> in a utility function if it weren't for the fact the use cases often entail
> performance-sensitive paths, and engines aren't reliable enough in my
> experience with inlining closures passed to non-builtins.
>
> On Wed, Oct 10, 2018 at 22:54 Jordan Harband  wrote:
>
>> It seems like your proposed `const value = map.putIfAbsent(key,
>> getExpensiveValue);` is achievable already with `const value = map.has(key)
>> ? map.get(key) : map.set(getExpensiveValue());` - am I understanding your
>> suggestion correctly?
>>
>> On Wed, Oct 10, 2018 at 12:46 AM Man Hoang  wrote:
>>
>>> Consider the following function
>>>
>>> ``` js
>>>
>>> /**
>>>
>>> * Parses the locale sensitive string [value] into a number.
>>>
>>> */
>>>
>>> export function parseNumber(
>>>
>>> value: string,
>>>
>>> locale: string = navigator.language
>>>
>>> ): number {
>>>
>>> let decimalSeparator = decimalSeparators.get(locale);
>>>
>>> if (!decimalSeparator) {
>>>
>>> decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];
>>>
>>> decimalSeparators.set(locale, decimalSeparator);
>>>
>>> }
>>>
>>>
>>>
>>> let cleanRegExp = regExps.get(decimalSeparator);
>>>
>>> if (!cleanRegExp) {
>>>
>>> cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');
>>>
>>> regExps.set(decimalSeparator, cleanRegExp);
>>>
>>> }
>>>
>>>
>>>
>>> value = value
>>>
>>> .replace(cleanRegExp, '')
>>>
>>> .replace(decimalSeparator, '.');
>>>
>>>
>>>
>>> return parseFloat(value);
>>>
>>> }
>>>
>>>
>>>
>>> const decimalSeparators = new Map();
>>>
>>> const regExps = new Map();
>>>
>>> ```
>>>
>>>
>>>
>>> This function can be simplified quite a bit as follows
>>>
>>> ``` js
>>>
>>> export function parseNumber(
>>>
>>> value: string,
>>>
>>> locale: string = navigator.language
>>>
>>> ): number {
>>>
>>> const decimalSeparator = decimalSeparators.putIfAbsent(
>>>
>>> locale, () => Intl.NumberFormat(locale).format(1.1)[1]);
>>>
>>>
>>>
>>> const cleanRegExp = regExps.putIfAbsent(
>>>
>>> decimalSeparator, () => new
>>> RegExp(`[^-+0-9${decimalSeparator}]`, 'g'));
>>>
>>>
>>>
>>> value = value
>>>
>>> .replace(cleanRegExp, '')
>>>
>>> .replace(decimalSeparator, '.');
>>>
>>>
>>>
>>> return parseFloat(value);
>>>
>>> }
>>>
>>> ```
>>>
>>> if `Map` has the following instance method
>>>
>>> ``` js
>>>
>>> export class Map {
>>>
>>> /**
>>>
>>>  * Look up the value of [key], or add a new value if it isn't there.
>>>
>>>  *
>>>
>>>  * Returns the value associated to [key], if there is one.
>>>
>>>  * Otherwise calls [ifAbsent] to get a new value, associates [key] to
>>>
>>>  * that value, and then returns the new value.
>>>
>>>  */
>>>
>>> putIfAbsent(key: K, ifAbsent: () => V): V {
>>>
>>> let v = this.get(key);
>>>
>>> if (v === undefined) {
>>>
>>> v = ifAbsent();
>>>
>>> this.set(key, v);
>>>
>>> }
>>>
>>> return v;
>>>
>>> }
>>>
>>> }
>>>
>>> ```
>>>
>>>
>>>
>>> Java's Map has a `putIfAbsent` method, which accepts a value rather than
>>> a function for the second parameter. This is not ideal as computing the
>>> value may be expensive. A function would allow the value to be computed
>>> lazily.
>>>
>>>
>>>
>>> References
>>>
>>> - [Dart] [Map.putIfAbsent](
>>> https://api.dartlang.org/stable/2.0.0/dart-core/Map/putIfAbsent.html)
>>>
>>> - [Java] [Map.putIfAbsent](
>>> https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#putIfAbsent-K-V-
>>> )
>>> ___
>>> 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: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Isiah Meadows
I presume you mean this?

```js
// Proposed
map.putIfAbsent(key, init)

// How you do it now
let value
if (map.has(key)) {
value = map.get(key)
} else {
map.set(key, value = init())
}
```

BTW, I'd like to see this make it myself, just slightly different:

- How you call it: `map.getOrPut(key, init, thisValue=undefined)`
- How `init` is called: `init.call(thisValue, key, map)`

This pattern is incredibly common for caching. It'd be nice if I didn't
have to repeat myself so much with it. I would be more willing to stuff it
in a utility function if it weren't for the fact the use cases often entail
performance-sensitive paths, and engines aren't reliable enough in my
experience with inlining closures passed to non-builtins.

On Wed, Oct 10, 2018 at 22:54 Jordan Harband  wrote:

> It seems like your proposed `const value = map.putIfAbsent(key,
> getExpensiveValue);` is achievable already with `const value = map.has(key)
> ? map.get(key) : map.set(getExpensiveValue());` - am I understanding your
> suggestion correctly?
>
> On Wed, Oct 10, 2018 at 12:46 AM Man Hoang  wrote:
>
>> Consider the following function
>>
>> ``` js
>>
>> /**
>>
>> * Parses the locale sensitive string [value] into a number.
>>
>> */
>>
>> export function parseNumber(
>>
>> value: string,
>>
>> locale: string = navigator.language
>>
>> ): number {
>>
>> let decimalSeparator = decimalSeparators.get(locale);
>>
>> if (!decimalSeparator) {
>>
>> decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];
>>
>> decimalSeparators.set(locale, decimalSeparator);
>>
>> }
>>
>>
>>
>> let cleanRegExp = regExps.get(decimalSeparator);
>>
>> if (!cleanRegExp) {
>>
>> cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');
>>
>> regExps.set(decimalSeparator, cleanRegExp);
>>
>> }
>>
>>
>>
>> value = value
>>
>> .replace(cleanRegExp, '')
>>
>> .replace(decimalSeparator, '.');
>>
>>
>>
>> return parseFloat(value);
>>
>> }
>>
>>
>>
>> const decimalSeparators = new Map();
>>
>> const regExps = new Map();
>>
>> ```
>>
>>
>>
>> This function can be simplified quite a bit as follows
>>
>> ``` js
>>
>> export function parseNumber(
>>
>> value: string,
>>
>> locale: string = navigator.language
>>
>> ): number {
>>
>> const decimalSeparator = decimalSeparators.putIfAbsent(
>>
>> locale, () => Intl.NumberFormat(locale).format(1.1)[1]);
>>
>>
>>
>> const cleanRegExp = regExps.putIfAbsent(
>>
>> decimalSeparator, () => new RegExp(`[^-+0-9${decimalSeparator}]`,
>> 'g'));
>>
>>
>>
>> value = value
>>
>> .replace(cleanRegExp, '')
>>
>> .replace(decimalSeparator, '.');
>>
>>
>>
>> return parseFloat(value);
>>
>> }
>>
>> ```
>>
>> if `Map` has the following instance method
>>
>> ``` js
>>
>> export class Map {
>>
>> /**
>>
>>  * Look up the value of [key], or add a new value if it isn't there.
>>
>>  *
>>
>>  * Returns the value associated to [key], if there is one.
>>
>>  * Otherwise calls [ifAbsent] to get a new value, associates [key] to
>>
>>  * that value, and then returns the new value.
>>
>>  */
>>
>> putIfAbsent(key: K, ifAbsent: () => V): V {
>>
>> let v = this.get(key);
>>
>> if (v === undefined) {
>>
>> v = ifAbsent();
>>
>> this.set(key, v);
>>
>> }
>>
>> return v;
>>
>> }
>>
>> }
>>
>> ```
>>
>>
>>
>> Java's Map has a `putIfAbsent` method, which accepts a value rather than
>> a function for the second parameter. This is not ideal as computing the
>> value may be expensive. A function would allow the value to be computed
>> lazily.
>>
>>
>>
>> References
>>
>> - [Dart] [Map.putIfAbsent](
>> https://api.dartlang.org/stable/2.0.0/dart-core/Map/putIfAbsent.html)
>>
>> - [Java] [Map.putIfAbsent](
>> https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#putIfAbsent-K-V-
>> )
>> ___
>> 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: Array.prototype.remove(item)

2018-10-10 Thread Sanford Whiteman
You need to cite your sources for the claim that "most of the tech
debt" in JavaScript product development is due to accidentally using
types other than 20-year-old built-ins and having to figure out the
daunting task of JSON serialization.

—— Sandy

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


Re: Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Jordan Harband
It seems like your proposed `const value = map.putIfAbsent(key,
getExpensiveValue);` is achievable already with `const value = map.has(key)
? map.get(key) : map.set(getExpensiveValue());` - am I understanding your
suggestion correctly?

On Wed, Oct 10, 2018 at 12:46 AM Man Hoang  wrote:

> Consider the following function
>
> ``` js
>
> /**
>
> * Parses the locale sensitive string [value] into a number.
>
> */
>
> export function parseNumber(
>
> value: string,
>
> locale: string = navigator.language
>
> ): number {
>
> let decimalSeparator = decimalSeparators.get(locale);
>
> if (!decimalSeparator) {
>
> decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];
>
> decimalSeparators.set(locale, decimalSeparator);
>
> }
>
>
>
> let cleanRegExp = regExps.get(decimalSeparator);
>
> if (!cleanRegExp) {
>
> cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');
>
> regExps.set(decimalSeparator, cleanRegExp);
>
> }
>
>
>
> value = value
>
> .replace(cleanRegExp, '')
>
> .replace(decimalSeparator, '.');
>
>
>
> return parseFloat(value);
>
> }
>
>
>
> const decimalSeparators = new Map();
>
> const regExps = new Map();
>
> ```
>
>
>
> This function can be simplified quite a bit as follows
>
> ``` js
>
> export function parseNumber(
>
> value: string,
>
> locale: string = navigator.language
>
> ): number {
>
> const decimalSeparator = decimalSeparators.putIfAbsent(
>
> locale, () => Intl.NumberFormat(locale).format(1.1)[1]);
>
>
>
> const cleanRegExp = regExps.putIfAbsent(
>
> decimalSeparator, () => new RegExp(`[^-+0-9${decimalSeparator}]`,
> 'g'));
>
>
>
> value = value
>
> .replace(cleanRegExp, '')
>
> .replace(decimalSeparator, '.');
>
>
>
> return parseFloat(value);
>
> }
>
> ```
>
> if `Map` has the following instance method
>
> ``` js
>
> export class Map {
>
> /**
>
>  * Look up the value of [key], or add a new value if it isn't there.
>
>  *
>
>  * Returns the value associated to [key], if there is one.
>
>  * Otherwise calls [ifAbsent] to get a new value, associates [key] to
>
>  * that value, and then returns the new value.
>
>  */
>
> putIfAbsent(key: K, ifAbsent: () => V): V {
>
> let v = this.get(key);
>
> if (v === undefined) {
>
> v = ifAbsent();
>
> this.set(key, v);
>
> }
>
> return v;
>
> }
>
> }
>
> ```
>
>
>
> Java's Map has a `putIfAbsent` method, which accepts a value rather than a
> function for the second parameter. This is not ideal as computing the value
> may be expensive. A function would allow the value to be computed lazily.
>
>
>
> References
>
> - [Dart] [Map.putIfAbsent](
> https://api.dartlang.org/stable/2.0.0/dart-core/Map/putIfAbsent.html)
>
> - [Java] [Map.putIfAbsent](
> https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#putIfAbsent-K-V-
> )
> ___
> 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.prototype.remove(item)

2018-10-10 Thread kai zhu
> Not every object in JS is intended to travel between client and server, or to 
> be stored in JSON. And if/when the class want to share some information, it 
> can easily translate its data to and from a JSON-friendly format.

hi Claude, agree to disagree.  its impossible to predict/design what should and 
shouldn’t travel between client <-> server in javascript product-development.  

the best you can do as an “architect” is to accept that *anything* 
of-consequence in javascript will eventually need to "leak" itself to the 
"client <-> server <-> db JSON/urlstring dance", over the normal-flow of 
UX-features getting added to a product;  and that much of the tech-debt in 
these projects arise from needless class constructor/serialization hacks to 
make that dance happen, when it wasn’t expected (and could’ve been avoided by 
sticking with plain JSON data-structures).

even in esoteric, seemingly non-web-related cases like using duktape in c++:  
why would anyone want to have embedded js-capability in such scenario?  the 
only use-case that comes to mind is for manipulating JSON data-structures, and 
again, passing plain JSON-data between "c++ program" <-> “external web-system"

kai zhu
kaizhu...@gmail.com


> On 11 Oct 2018, at 5:14 AM, Claude Pache  wrote:
> 
> 
> 
>> Le 10 oct. 2018 à 23:17, kai zhu  a écrit :
>> 
>> hi Man, i don’t have strong opinion on Array.prototype.remove, but i have 
>> strong opinion against your use-case to subclass/extend Array.  from a 
>> product-development perspective, you're creating unnecessary 
>> integration-headaches by having the client <-> server system pass around 
>>  instances instead of plain JSON arrays.
> 
> Not every object in JS is intended to travel between client and server, or to 
> be stored in JSON. And if/when the class want to share some information, it 
> can easily translate its data to and from a JSON-friendly format. (Sorry, I’m 
> not motivated to read the rest of your e-mail.)
> 
> —Claude 
> 

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


Re: Backstory/rationale for disallowing -0 in Map keys and Sets?

2018-10-10 Thread Jordan Harband
The unfortunate result, however, is that a subclass that is *more*
restrictive than the base class is not possible to write robustly - namely,
if someone does `Set.prototype.add.call`, they'll bypass any of the
criteria you've set up in the subclass.

I would have vastly preferred that the base class for both Map and Set used
SameValue, and I'd have found a "SameValueZero" subclass to be much more
trivial to write robustly than a "SameValue" subclass is now. That ship,
unfortunately, has long since sailed.

On Wed, Oct 10, 2018 at 11:09 AM T.J. Crowder <
tj.crow...@farsightsoftware.com> wrote:

> On Wed, Oct 10, 2018 at 7:03 PM Allen Wirfs-Brock
>  wrote:
> > Yes, exactly.
>
> Thanks!
>
> -- T.J. Crowder
> ___
> 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.prototype.remove(item)

2018-10-10 Thread Jordan Harband
Man: `add` doesn't need to return a boolean, because it always results in
the item being in the collection after the fact. You could subclass Set,
and make `.add` do that, though, if you like! Alternatively, you could use
`.has` prior to calling `.add`, to get your boolean value.

On Wed, Oct 10, 2018 at 1:01 AM Man Hoang  wrote:

> The problem with `Set` is that its `add` method returns `this` instead of
> `boolean`. If `Set.prototype.add` returned `boolean`, I would have used
> `Set`.
>
>
>
> That’s why in the `select` method of my sample code, I use a custom
> defined method named `pushIfAbsent`. The actual type of `_values` is not
> `Array` but a subclass of `Array`.
>
> ``` js
>
> export class MyArray extends Array {
>
> /**
>
>  * Adds [item] to the end of this array if it's not already in this
> array.
>
>  *
>
>  * Returns `true` is [item] was added, `false` otherwise.
>
>  */
>
> pushIfAbsent(item: E): boolean {
>
> if (!this.includes(item)) {
>
> this.push(item);
>
> return true;
>
> }
>
> return false;
>
> }
>
>
>
> /**
>
>  * Removes the first occurrence of [item] from this array.
>
>  *
>
>  * Returns `true` if [item] was in this array, `false` otherwise.
>
>  */
>
> remove(item: E): boolean {
>
> const i = this.indexOf(item);
>
> if (i >= 0) {
>
> this.splice(i, 1);
>
> return true;
>
> }
>
> return false;
>
> }
>
> }
>
> ```
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.remove(item)

2018-10-10 Thread Claude Pache


> Le 10 oct. 2018 à 23:17, kai zhu  a écrit :
> 
> hi Man, i don’t have strong opinion on Array.prototype.remove, but i have 
> strong opinion against your use-case to subclass/extend Array.  from a 
> product-development perspective, you're creating unnecessary 
> integration-headaches by having the client <-> server system pass around 
>  instances instead of plain JSON arrays.

Not every object in JS is intended to travel between client and server, or to 
be stored in JSON. And if/when the class want to share some information, it can 
easily translate its data to and from a JSON-friendly format. (Sorry, I’m not 
motivated to read the rest of your e-mail.)

—Claude 

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


Re: Array.prototype.remove(item)

2018-10-10 Thread kai zhu
hi Man, i don’t have strong opinion on Array.prototype.remove, but i have 
strong opinion against your use-case to subclass/extend Array.  from a 
product-development perspective, you're creating unnecessary 
integration-headaches by having the client <-> server system pass around 
 instances instead of plain JSON arrays.

i remain unconvinced of any real-world benefit to subclassing Array, that 
justifies the cost-added to already painful task of debugging end-to-end 
communication-issues between client <-> server.  your web-project will have a 
less-painful integration/qa process, if you stick with plain JSON arrays 
employing static-functions instead:

```javascript
/*jslint devel*/
(function () {
"use strict";
var myArray1;
function arrayRemoveItem(array, item) {
/**
 * This static-function will:
 * Remove the first occurrence of [item] from this array.
 * Return `true` if [item] was in this array, `false` otherwise.
 */
var i = array.indexOf(item);
if (i >= 0) {
array.splice(i, 1);
return true;
}
return false;
}
myArray1 = [1, 2, 3, 4]; // [1, 2, 3, 4]
console.log(arrayRemoveItem(myArray1, 2)); // true
console.log(myArray1); // [1, 3, 4]
}());
```

kai zhu
kaizhu...@gmail.com



> On 10 Oct 2018, at 3:01 PM, Man Hoang  wrote:
> 
> The problem with `Set` is that its `add` method returns `this` instead of 
> `boolean`. If `Set.prototype.add` returned `boolean`, I would have used `Set`.
>  
> That’s why in the `select` method of my sample code, I use a custom defined 
> method named `pushIfAbsent`. The actual type of `_values` is not `Array` but 
> a subclass of `Array`.
> ``` js
> export class MyArray extends Array {
> /**
>  * Adds [item] to the end of this array if it's not already in this array.
>  * 
>  * Returns `true` is [item] was added, `false` otherwise.
>  */
> pushIfAbsent(item: E): boolean {
> if (!this.includes(item)) {
> this.push(item);
> return true;
> }
> return false;
> }
>  
> /**
>  * Removes the first occurrence of [item] from this array.
>  * 
>  * Returns `true` if [item] was in this array, `false` otherwise.
>  */
> remove(item: E): boolean {
> const i = this.indexOf(item);
> if (i >= 0) {
> this.splice(i, 1);
> return true;
> }
> return false;
> }
> }
> ```
> ___
> 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: Backstory/rationale for disallowing -0 in Map keys and Sets?

2018-10-10 Thread T.J. Crowder
On Wed, Oct 10, 2018 at 7:03 PM Allen Wirfs-Brock
 wrote:
> Yes, exactly.

Thanks!

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


Re: Backstory/rationale for disallowing -0 in Map keys and Sets?

2018-10-10 Thread Allen Wirfs-Brock


> On Oct 10, 2018, at 3:42 AM, T.J. Crowder  
> wrote:
> 
> the ambiguity that -0 and +0 are often hard to distinguish (Number's 
> `toString` returns `"0"` for both, for instance; operations involving them 
> largely don't care about the pseudo-sign of 0). Is that the rationale? 
> Basically, avoid a footgun while ensuring consistency?

Yes, exactly.

Also, at that time the proposed comparator parameter was already restricted to 
selecting between SameValue and SameValue0 because of concerns/open issues 
about an unrestricted comparator parameter.  After it was demonstrated that a 
subclass that distinguished ±0 was fairly trivial to write the comparator 
parameter was eliminated.

The assumption was that someday an extension proposal to add a generalized 
comparator parameter would be brought forward and considered.

Allen

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


Re: The "gathering developer feedback" utopia.

2018-10-10 Thread Terence M. Bandoian

+1  Ideas should be judged on their merit.

-Terence Bandoian


On 10/10/2018 5:12 AM, Andrea Giammarchi wrote:

Daniel Ehrenberg wrote [1] the following:

> I'd recommend starting with making a library which does this, and 
gathering broad developer feedback, before proposing for standardization.


it was a genuine extra answer to the question:

> do you think [for] this [proposal] is worth going through the process?

Now here the issue: if you don't have thousand twitter followers and 
you don't work for Google, Microsoft or Facebook, the "gathering 
broader feedback" is just a wall that every developer with a good idea 
but not an easy way to reach some broader feedback will hit.


I have libraries that got few stars on GitHub, I haven't actively 
promoted them, but are downloaded 13 million times per month on npm, 
yet nobody cares, and most don't even know such library exists.


I have other ideas never seen before that will never see the "standard 
light" because either people after me overlapped with their version of 
my idea but are closer to standard bodies (working for Google, as 
example) or I have consistent lower reach than united groups (googles 
re-tweeting googlers stuff or similar).


Bear in mind I'm not necessarily pointing fingers to anyone, and I 
believe it's normal that most followed companies with they devrel 
people and their team would promote their ideas as a united group, but 
telling people proposing new standards that these will hardly be 
considered until there is broader community interest seems elitist for 
no reasons and an unnecessary, or unbreakable wall, for newcomers.


As summary, I don't even like that specific Array#pluck proposal, but 
it would be great if this ML could be open to everyone, not just those 
with stars on GitHub and many followers.


I know Daniel wrote that in good faith, but having an official 
statement written somewhere about this might be less discouraging for 
newcomers.


Best Regards.

[1] https://github.com/tc39/ecma262/issues/1324#issuecomment-428503827


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


Re: Re: .. cascade operator

2018-10-10 Thread Luan Nico
I agree with this, Dart has the exact thing and it's amazing. Not sure
what's the status or reason for not following through, though.

On Wed, Oct 10, 2018 at 3:54 AM Man Hoang  wrote:

> This operator should have been added years ago. It would enable many APIs
> to return more appropriate results instead of `this`.
>
>
>
> For example, `Set.prototype.add(value)` could return a boolean indicating
> if an item was actually added instead of `this`.
>
>
> ___
> 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


Backstory/rationale for disallowing -0 in Map keys and Sets?

2018-10-10 Thread T.J. Crowder
Negative zero (-0) is the only value you can't use as a Map key or a Set
value. Map's [`set`][1] and Set's [`add`][2] both explicitly replace it
with +0. MDN makes a point of saying that "early drafts" of the ES2015 spec
treated +0 and -0 as distinct, but that "changed" in ES2015. Looking at
some early drafts, at some stage Map and Set used SameValue (so you could
have both +0 and -0 as Map keys or in a Set), then went through a period
where you could specify a "comparator" for them (so a given instance would
use SameValue or SameValueZero). Then that was removed; the final spec uses
SameValueZero and has `set` and `add` replace -0 with +0.

Using SameValueZero and converting -0 to +0 when storing does have the
effect of ensuring consistency: You don't end up with two sets (for
instance) with different values (-0 and +0) that Set's comparison logic
(SameValueZero) considers the same. (But then, so would using SameValue and
converting from -0 to +0 earlier in the `set` and `add` algorithsm.) Using
SameValue and allowing -0 would also ensure consistency, but with the
ambiguity that -0 and +0 are often hard to distinguish (Number's `toString`
returns `"0"` for both, for instance; operations involving them largely
don't care about the pseudo-sign of 0). Is that the rationale? Basically,
avoid a footgun while ensuring consistency?

Thanks,

-- T.J. Crowder

[1]: https://tc39.github.io/ecma262/#sec-map.prototype.set
[2]: https://tc39.github.io/ecma262/#sec-set.prototype.add
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


The "gathering developer feedback" utopia.

2018-10-10 Thread Andrea Giammarchi
Daniel Ehrenberg wrote [1] the following:

> I'd recommend starting with making a library which does this, and
gathering broad developer feedback, before proposing for standardization.

it was a genuine extra answer to the question:

> do you think [for] this [proposal] is worth going through the process?

Now here the issue: if you don't have thousand twitter followers and you
don't work for Google, Microsoft or Facebook, the "gathering broader
feedback" is just a wall that every developer with a good idea but not an
easy way to reach some broader feedback will hit.

I have libraries that got few stars on GitHub, I haven't actively promoted
them, but are downloaded 13 million times per month on npm, yet nobody
cares, and most don't even know such library exists.

I have other ideas never seen before that will never see the "standard
light" because either people after me overlapped with their version of my
idea but are closer to standard bodies (working for Google, as example) or
I have consistent lower reach than united groups (googles re-tweeting
googlers stuff or similar).

Bear in mind I'm not necessarily pointing fingers to anyone, and I believe
it's normal that most followed companies with they devrel people and their
team would promote their ideas as a united group, but telling people
proposing new standards that these will hardly be considered until there is
broader community interest seems elitist for no reasons and an unnecessary,
or unbreakable wall, for newcomers.

As summary, I don't even like that specific Array#pluck proposal, but it
would be great if this ML could be open to everyone, not just those with
stars on GitHub and many followers.

I know Daniel wrote that in good faith, but having an official statement
written somewhere about this might be less discouraging for newcomers.

Best Regards.

[1] https://github.com/tc39/ecma262/issues/1324#issuecomment-428503827
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Array.prototype.remove(item)

2018-10-10 Thread Man Hoang
The problem with `Set` is that its `add` method returns `this` instead of 
`boolean`. If `Set.prototype.add` returned `boolean`, I would have used `Set`.

That’s why in the `select` method of my sample code, I use a custom defined 
method named `pushIfAbsent`. The actual type of `_values` is not `Array` but a 
subclass of `Array`.
``` js
export class MyArray extends Array {
/**
 * Adds [item] to the end of this array if it's not already in this array.
 *
 * Returns `true` is [item] was added, `false` otherwise.
 */
pushIfAbsent(item: E): boolean {
if (!this.includes(item)) {
this.push(item);
return true;
}
return false;
}

/**
 * Removes the first occurrence of [item] from this array.
 *
 * Returns `true` if [item] was in this array, `false` otherwise.
 */
remove(item: E): boolean {
const i = this.indexOf(item);
if (i >= 0) {
this.splice(i, 1);
return true;
}
return false;
}
}
```
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Proposal: Add Map.prototype.putIfAbsent

2018-10-10 Thread Man Hoang
Consider the following function
``` js
/**
* Parses the locale sensitive string [value] into a number.
*/
export function parseNumber(
value: string,
locale: string = navigator.language
): number {
let decimalSeparator = decimalSeparators.get(locale);
if (!decimalSeparator) {
decimalSeparator = Intl.NumberFormat(locale).format(1.1)[1];
decimalSeparators.set(locale, decimalSeparator);
}

let cleanRegExp = regExps.get(decimalSeparator);
if (!cleanRegExp) {
cleanRegExp = new RegExp(`[^-+0-9${decimalSeparator}]`, 'g');
regExps.set(decimalSeparator, cleanRegExp);
}

value = value
.replace(cleanRegExp, '')
.replace(decimalSeparator, '.');

return parseFloat(value);
}

const decimalSeparators = new Map();
const regExps = new Map();
```

This function can be simplified quite a bit as follows
``` js
export function parseNumber(
value: string,
locale: string = navigator.language
): number {
const decimalSeparator = decimalSeparators.putIfAbsent(
locale, () => Intl.NumberFormat(locale).format(1.1)[1]);

const cleanRegExp = regExps.putIfAbsent(
decimalSeparator, () => new RegExp(`[^-+0-9${decimalSeparator}]`, 'g'));

value = value
.replace(cleanRegExp, '')
.replace(decimalSeparator, '.');

return parseFloat(value);
}
```
if `Map` has the following instance method
``` js
export class Map {
/**
 * Look up the value of [key], or add a new value if it isn't there.
 *
 * Returns the value associated to [key], if there is one.
 * Otherwise calls [ifAbsent] to get a new value, associates [key] to
 * that value, and then returns the new value.
 */
putIfAbsent(key: K, ifAbsent: () => V): V {
let v = this.get(key);
if (v === undefined) {
v = ifAbsent();
this.set(key, v);
}
return v;
}
}
```

Java's Map has a `putIfAbsent` method, which accepts a value rather than a 
function for the second parameter. This is not ideal as computing the value may 
be expensive. A function would allow the value to be computed lazily.

References
- [Dart] 
[Map.putIfAbsent](https://api.dartlang.org/stable/2.0.0/dart-core/Map/putIfAbsent.html)
- [Java] 
[Map.putIfAbsent](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#putIfAbsent-K-V-)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.remove(item)

2018-10-10 Thread Claude Pache
For that specific example, I think that a Set is more appropriate:

``` js
export class Selector {
private _set = new Set;
 
get values(): ReadonlyArray {
return Array.from(this._set);
// although it might be better to return an iterator: return 
this._set.values();
}

deselect(value: T): boolean {
if (this._set.delete(value)) {
this.selectionChanged([], [value]);
return true;
}
return false;
}

// etc.
}
```

More generally, each time you are tempted to use an 
add()/remove()/toggle()/contains()/etc() method on an Array, you should ask 
yourself if it would not be better (more efficient, clearer intent, more 
concise, ...) to use a Set instead.

—Claude


> Le 10 oct. 2018 à 08:30, Man Hoang  a écrit :
> 
> The benefits are
> - efficient (memory & speed)
> - clear intent
> - concise
>  
> There are always use cases where you want to mutate arrays.
>  
> How would you rewrite the following `deselect` method using `filter`?
>  
> ``` js
> export class Selector {
> private _values: T[] = [];
>  
> get values(): ReadonlyArray {
> return this._values;
> }
>  
> /**
>  * Removes [value] from the list of selected items.
>  * 
>  * Returns `true` if [value] was previously selected, `false` otherwise.
>  */
> deselect(value: T): boolean {
> if (this._values.remove(value)) {
> this.selectionChanged([], [value]);
> return true;
> }
> return false;
> }
>  
> /**
>  * Adds [value] to the list of selected items.
>  * 
>  * Returns `true` if [value] was not previously selected, `false` 
> otherwise.
>  */
> select(value: T): boolean {
> if (this._values.pushIfAbsent(value)) {
> this.selectionChanged([value], []);
> return true;
> }
> return false;
> }
>  
> protected selectionChanged(addedValues, removedValues) {
> // Do something such as firing an event.
> }
> }
> ```
> ___
> 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: Re: (Map|Set|WeakMap)#set() returns `this` ?

2018-10-10 Thread Man Hoang
What JS needs is a [cascade 
operator](https://esdiscuss.org/topic/cascade-operator). With this operator, 
property accessors and methods can be effectively chained without requiring 
methods to return `this`.

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