es-discuss@mozilla.org

2021-03-04 Thread Andrea Giammarchi
ts 1
>
> ```
>
>
>
> In Augusto’s example, you would have your choice of object passing or
> variable passing:
>
>
>
> ```js
>
> function foo(ref value) {
>   value = 'foo';
> }
>
> function second(source) {
>
>   {
>
>   let { ref value } = source; // NOTE `value` is a `Reference` object here
> console.log(typeof value); // object
> foo(value);
>
> }
>
>
>
> // The above would be the same as this
>
> {
> let value = ref source.value; // `value` is a `Reference` object here
>
>   console.log(typeof value); // object
> foo(value);
>   }
>
> }
>
>
>
> second({ value: "bar" });
>
> ```
>
>
>
> I’m still considering the destructuring side of things. Whether you are
> creating a `Reference` or dereferencing it is clear for some patterns:
>
>
>
> ```js
> // (a) `ref` Destructuring Targets
>
> // dereferences `obj.x` if `obj.x` is a `Reference`
>
> let { x: ref x } = obj;
>
> // This is equivalent to the following:
>
> let ref x = obj.x; // Probably not what you want…
>
>
>
>
>
> // (b) `ref` Destructuring Bindings
>
> // creates a `Reference` for `obj.x` and stores it in `x`, so `x` is a
> reified `Reference`.
>
> let { ref x: x } = obj;
>
>
>
> // This is equivalent to the following:
>
> let x = ref obj.x; // Probably not what you want either…
>
>
>
>
>
> // (c) `ref` Destructuring Targets **and** Bindings
>
> // Create a `Reference` for `obj.x` and dereference it in `x`:
>
> let { ref x: ref x } = obj;
>
> // This is equivalent to the following:
> let ref x = ref obj.x; // Probably what you wanted
> ```
>
> However, this is less clear for shorthand destructuring assignments or
> array destructuring:
>
>
>
> ```js
>
> let { ref x } = obj; // did you mean (a), (b), or (c) above?
>
> let [ref x] = ar; // did you mean (a), (b), or (c) above?
>
> ```
>
>
>
> In these two examples, you **probably** want (c), but there are valid
> reasons for wanting (a) or (b) as well. The explainer for the proposal
> currently chooses (a), but I’ve been reconsidering. None of this is set in
> stone (since this proposal isn’t even at Stage 1 yet), and I’m open to
> suggestions and discussion on the issue tracker.
>
>
>
> Ron
>
>
>
> *From:* es-discuss  * On Behalf Of *Andrea
> Giammarchi
> *Sent:* Thursday, March 4, 2021 12:43 AM
> *To:* Augusto Moura 
> *Cc:* es-discuss 
> *Subject:* [EXTERNAL] Re: Destructuring by &reference
>
>
>
> > How will you prevent the passing of the object down the pipe?
>
>
>
> ```js
>
> const downThePipe = ({&source}) => {
>
>   // you can read source
>
>   source;
>
>   // you can set source
>
>   source = 'blah';
>
>   // you can't know where source comes from
>
>   // but you could propagate that reference further
>
>   evenFurtherDown({&source, any: 'value'}, Math.random());
>
> };
>
>
>
> downThePipe({
>
>   secret: 'nothing out there can reach me',
>
>   get source() { 'this object'; },
>
>   set source(value) {
>
> console.log('hello', value, this.secret);
>
>   }
>
> });
>
> ```
>
>
>
> You can pass objects already in JS so this changes nothing in terms of
> logic, except the callback has a way to signal reactive properties or
> retrieved methods.
>
>
>
> Any boilerplate with Proxies would be slower and more convoluted, so this
> syntax simplieis all the code you wrote via an explicit intent: the
> callback would like to invoke, or update an accessor, of the given object,
> without holding, or having, the whole object in its scope.
>
>
>
> I hope this explains a bit better why I think this feature would be
> extremely cool. Polyfills won't need to do much, code remains short and
> clean, accessors/reactive properties becomes instantly clear (they say
> accessors are a footgun, here we're flagging these for better awareness)
> and methods can be invoked with the right context too, without needing
> whole objects references around.
>
>
>
>
>
> On Wed, Mar 3, 2021 at 9:03 PM Augusto Moura 
> wrote:
>
> > that's basically the entirety of the syntax sugar proposals since
> ES2015, right?
>
> Definitely no, but talking about the syntax additions since ES2015, they
> are in one or more of the categories below:
> - avoid known footguns in the language (arrow functions and lexical this,
> classes and prototype, let/const and block scoping, nullish coalescing
> operator

es-discuss@mozilla.org

2021-03-04 Thread Andrea Giammarchi
> How will you prevent the passing of the object down the pipe?

```js
const downThePipe = ({&source}) => {
  // you can read source
  source;
  // you can set source
  source = 'blah';
  // you can't know where source comes from
  // but you could propagate that reference further
  evenFurtherDown({&source, any: 'value'}, Math.random());
};

downThePipe({
  secret: 'nothing out there can reach me',
  get source() { 'this object'; },
  set source(value) {
console.log('hello', value, this.secret);
  }
});
```

You can pass objects already in JS so this changes nothing in terms of
logic, except the callback has a way to signal reactive properties or
retrieved methods.

Any boilerplate with Proxies would be slower and more convoluted, so this
syntax simplieis all the code you wrote via an explicit intent: the
callback would like to invoke, or update an accessor, of the given object,
without holding, or having, the whole object in its scope.

I hope this explains a bit better why I think this feature would be
extremely cool. Polyfills won't need to do much, code remains short and
clean, accessors/reactive properties becomes instantly clear (they say
accessors are a footgun, here we're flagging these for better awareness)
and methods can be invoked with the right context too, without needing
whole objects references around.


On Wed, Mar 3, 2021 at 9:03 PM Augusto Moura 
wrote:

> > that's basically the entirety of the syntax sugar proposals since
> ES2015, right?
>
> Definitely no, but talking about the syntax additions since ES2015, they
> are in one or more of the categories below:
> - avoid known footguns in the language (arrow functions and lexical this,
> classes and prototype, let/const and block scoping, nullish coalescing
> operator, etc.)
> - syntax sugars with strong community feedback AND battle proven prior art
> (classes, destructuring, string templates, rest, spread and default
> values, async/await, etc.)
> - introducing or specifying new mechanisms that didn't exist before in
> ecma (modules, classes, varargs, etc.)
>
> > also proxy and globalThis are *really* unrelated to this
>
> Proxy and globalThis (and the `with` statement for that matter), are
> mechanisms of value indirection aside from the "classic" instance properties
>
> >  while leaking objects all over down the pipe is my major concern,
> something this proposal avoids, as no code will have a reference to the
> entirety of the source object, they'll deal with a known property name
> passed by reference, incapable of changing anything else in the source
> object ... so it's rather a signal, than a convention.
>
> How will you prevent the passing of the object down the pipe? You mean the
> reference variable being passed to another function and setting the prop
> into the source object?
> ```js
> function foo(source) {
>   let { &value } = source;
>   value = 'foo';
> }
>
> function second(source) {
>   // You still need to pass the object forward right?
>   foo(source)
>
>   // Or the proposal is something like this
>   let { &value } = source;
>   foo(value);
>   // and then if foo sets the value argument it should reflect in source
> }
> ```
>
> Also the usual way of preventing the "passing the full object down"
> problem is restricting the contract with other functions using a
> wrapper/proxy, a well defined more specific interface or in the readonly
> case just omitting the other properties
>
> ```ts
> // Wrapper way
> class Nameable {
>   constructor(instance) { this.#obj = instance }
>   get name() { return this.#obj.name }
>   set name(newName) { this.#obj.name = newName }
> }
>
> function printName(nameable) {
>   console.log(nameable.name)
>   nameable.name += ' [printed]'
> }
> function foo(source) {
>   printName(new Nameable(source))
> }
> foo({ name: 'foo', type: 'pojo' })
>
> // Well defined contract way (using Typescript, but you could rely on duck
> typing if you trust the good manners of the developers)
> interface Nameable {
>   name: string;
> }
> interface Pojo extends Nameable {
>   type: string;
> }
>
> function printName(nameable: Nameable) {
>   console.log(nameable.name)
>   nameable.name += ' [printed]'
>   // the function still can access the type field by ignoring the typing,
> but at this point this is the least scary thing a developer in a app
> }
> function foo(source: Pojo) {
>   printName(source)
> }
>
> // Omit and readonly way
> function printName(nameable) { /* ... */ }
> function foo(source) {
>   printName(pick(source, ['name']))
> }
> ```
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


es-discuss@mozilla.org

2021-03-03 Thread Andrea Giammarchi
to expand further: you *could* access such reference via `arguments[0]`,
but *that* won't be possible with arrow functions, as example, so that
`({&reactive}, maybe) => { if (maybe) reactive = true; }` is another
pattern that doesn't need the whole object around, or to be propagated,
when you can pass it via `{&reactive}` to anything else, covering then the
`arguments` point too.

On Wed, Mar 3, 2021 at 6:44 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> > the proposal is just a debatable syntax sugar for something we already
> can do
>
> that's basically the entirety of the syntax sugar proposals since ES2015,
> right? also proxy and globalThis are *really* unrelated to this, imho,
> while leaking objects all over down the pipe is my major concern, something
> this proposal avoids, as no code will have a reference to the entirety of
> the source object, they'll deal with a known property name passed by
> reference, incapable of changing anything else in the source object ... so
> it's rather a signal, than a convention.
>
> this means composability, different classes/prototypes passed as
> arguments, and the certainty nothing can inspect, change, or deal, with the
> source, which means increased security, as opposite to pass instances and
> whole objects references around.
>
> You have a reference to a property, you don't see its source.
>
>
> On Wed, Mar 3, 2021 at 6:19 PM Augusto Moura 
> wrote:
>
>> > ```js
>> > function stuff(source, extra) {
>> >   const {value, method} = source;
>> >
>> >   if (condition)
>> > method.call(source);
>> >
>> >   if (value === extra)
>> > source.value = 'no more';
>> > }
>> > ```
>>
>> I mean, in this case you can skip destructuring altogether, having a one
>> way and way only of value indirection is a Pretty Good Thing™ (even though
>> we already have proxys, globalThis and other indirection shenanigans), I
>> never felt annoyed of just using `source.value` or `source.method()`
>> instead of `value` and `method()`, again the proposal is just a debatable
>> syntax sugar for something we already can do. I wonder if we could ever do
>> the reference thingy in user-land with variable level decorators, if it
>> ever gets discussed again in the meetings. Would be still kinda fishy to
>> propose and implement
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


es-discuss@mozilla.org

2021-03-03 Thread Andrea Giammarchi
> the proposal is just a debatable syntax sugar for something we already
can do

that's basically the entirety of the syntax sugar proposals since ES2015,
right? also proxy and globalThis are *really* unrelated to this, imho,
while leaking objects all over down the pipe is my major concern, something
this proposal avoids, as no code will have a reference to the entirety of
the source object, they'll deal with a known property name passed by
reference, incapable of changing anything else in the source object ... so
it's rather a signal, than a convention.

this means composability, different classes/prototypes passed as arguments,
and the certainty nothing can inspect, change, or deal, with the source,
which means increased security, as opposite to pass instances and whole
objects references around.

You have a reference to a property, you don't see its source.


On Wed, Mar 3, 2021 at 6:19 PM Augusto Moura 
wrote:

> > ```js
> > function stuff(source, extra) {
> >   const {value, method} = source;
> >
> >   if (condition)
> > method.call(source);
> >
> >   if (value === extra)
> > source.value = 'no more';
> > }
> > ```
>
> I mean, in this case you can skip destructuring altogether, having a one
> way and way only of value indirection is a Pretty Good Thing™ (even though
> we already have proxys, globalThis and other indirection shenanigans), I
> never felt annoyed of just using `source.value` or `source.method()`
> instead of `value` and `method()`, again the proposal is just a debatable
> syntax sugar for something we already can do. I wonder if we could ever do
> the reference thingy in user-land with variable level decorators, if it
> ever gets discussed again in the meetings. Would be still kinda fishy to
> propose and implement
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


es-discuss@mozilla.org

2021-03-03 Thread Andrea Giammarchi
The way I see it: it's just a convention/shortcut to have the destructured
object around.

```js
function augment({&value}, testCase) {
  if (/thing/.test(testCase))
value += testCase;
}

let any = {value: ''};
augment(any, 'thing');
```

The magical behavior goal is to define side effects when overwriting
properties ... for instance:

  * a destructured property, as getter, is just a value
  * every destructured property can be overwritten ... as these are just
references

Now here some wonder:

```js
let any = {
  get value() { return 'no setter'; },
  method() {
console.log(this.value);
  }
};

function stuff({&value, &method}, extra) {
  method(); // "no setter"

  // throws an error
  value = extra;
}
```

Basically, at the engine level, is just a shortcut for having the original
destructure object around, so that both `&value` and `&method` would behave
exactly like `object.value = ...` or `object.method();`

I personally don't know how many times I wanted this simplicity, as
opposite of going through this pattern:

```js
function stuff(source, extra) {
  const {value, method} = source;

  if (condition)
method.call(source);

  if (value === extra)
source.value = 'no more';
}
```

The constant change between having the value once, then eventually needing
to remember the source is missing, so the function needs refactoring, or it
needs binding, or it needs ... you name it, I think referencing the source
object somehow, would allow a lot of refactoring, smaller code, and easier
to reason about, in IDEs (special highlights for referenced variables), in
developers intent (no need to grab the source repeatedly when updates are
needed), and in clarity (having an explicit & in destructuring describes
the intent of wanting to deal with that value as reference).

My only concern here would be: what if we pass that value to another
signature? Well, as long as we don't also have a way to pass such value as
reference, in example, "restructuring", as in `callback({&value, other})`
instead of just `callback({value, other})`, this should be a no-brainer,
but maybe the two ideas should be spec'd together, and also ship together,
so that you can propagate a single "*reaction point*" down the lane,
without leaking the whole object across the whole lane.

I hope this makes sense, but that's the idea behind. The fact C can point
at pointers and force-update this but JS needs whole objects propagations
everywhere, in a highly reactive situation, like the one we have these
days, bugs me way too much.

Regards 👋


On Wed, Mar 3, 2021 at 4:47 PM Augusto Moura 
wrote:

> I don't know, the by reference destructuring seems a bit too much magical,
> a scoped variable that sets to a property to a object just sounds like the
> old `with` statement but reduced and more explicit, given is just a sugar
> and currently the problem is not a great of a pain point I would be very
> picky a proposal like that, any prior art in other languages?
>
> Also, from a grammar/vendor implementation standpoint I would imagine the
> definition of a by reference variable bind would be kinda fishy, I might be
> wrong though
>
> Em ter., 2 de mar. de 2021 às 21:03, Claudia Meadows <
> cont...@isiahmeadows.com> escreveu:
>
>> I would like to see this happen, though I'd like to see it integrated
>> with reified refs. (I know there's a proposal laying around somewhere
>> drafted up by a current or former TC39 person, but I can't find it.)
>>
>> -
>>
>> Claudia Meadows
>> cont...@isiahmeadows.com
>>
>>
>> On Tue, Mar 2, 2021 at 11:05 AM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> Another one (cit. DJ Khaled)
>>>
>>> has "by reference" ever been considered as "yet another JS syntax" ???
>>>
>>> let object = {value: 1};
>>> let {&value} = object;
>>> value = 2;
>>>
>>> object.value; // 2
>>>
>>> allowed everywhere destructuring is possible, throwing for frozen
>>> properties ... is this just meh? .. .'cause I think, specially for function
>>> signatures declaration, it might make a difference, when mutability matters.
>>>
>>> Cheers 👋
>>>
>>> P.S. for transpilers this would simply carry, repeatedly, the initial
>>> reference.prop around, instead of using just prop.
>>>
>>> ___
>>> 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
>>
>
>
> --
> Atenciosamente,
>
> Augusto Borges de Moura
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


es-discuss@mozilla.org

2021-03-02 Thread Andrea Giammarchi
Another one (cit. DJ Khaled)

has "by reference" ever been considered as "yet another JS syntax" ???

let object = {value: 1};
let {&value} = object;
value = 2;

object.value; // 2

allowed everywhere destructuring is possible, throwing for frozen
properties ... is this just meh? .. .'cause I think, specially for function
signatures declaration, it might make a difference, when mutability matters.

Cheers 👋

P.S. for transpilers this would simply carry, repeatedly, the initial
reference.prop around, instead of using just prop.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Bind operator ... for destructuring

2021-01-13 Thread Andrea Giammarchi
Hello there 👋
  this is going to be quick: how about using the bind operator *at least*
for destructuring?

```js
// today
function util(ref) {
  if (ref.prop === 1)
ref.method(2);
}

// tomorrow?
function util({prop, ::method}) {
  if (prop === 1)
method(2);
}
```

Such shortcut would simplify a lot of extra variables declarations and/or
destructuring, both in the DOM world utilities, and in general in various
helpers.

Thoughts?

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


Re: Proposal: Function.prototype.bindContext

2020-09-17 Thread Andrea Giammarchi
I'm not sure I'm following, but I'm not here to find solutions, I already
have solutions, I'm here to propose a new `Function.prototype.bindContext`
method that doesn't require any user-land discussion/prototype pollution.

Thanks.

On Thu, Sep 17, 2020 at 9:25 PM Adam Eisenreich  wrote:

> This should able to be done via two nested WakMap,
>
> First level would be the function and the second the context or vice
> versa. This should be able to give you the same bound function while both
> are avaible, but should clear itself once the reference to function/context
> is lost.
>
> -- Původní e-mail --
> Od: Andrea Giammarchi 
> Komu: es-discuss@mozilla.org 
> Datum: 17. 9. 2020 21:03:45
> Předmět: Proposal: Function.prototype.bindContext
>
> I've found myself (once again) polluting the `Function.prototype` with a
> lazy method that, once invoked, grants that the returned bound function is
> always the same, per context.
>
> # Use Case
>
> It's still a common footgun to add events either via `context.method` or
> via `context.method.bind(context)`, where the former footgan would invoke
> `method` with a global context/undefined instead of the expected context,
> while the latter would make it impossible to ever remove that listener
> later on.
>
> It's also common to use methods for timers sensitive things, and it's
> indeed not by accident that `console` got "self bound", or provided as
> namespace, when it used to throw if `setTimeout(console.log, 100, value)`
> was used, for example.
>
> # Proposal
>
> Provide a lazy `bindContext` method that grants that if a method/function
> bound the same context before, it always returns the same reference.
>
> # Implementation / Polyfill (lazy version)
>
> ```js
> Function.prototype.bindContext = function (context) {
>   const _ = new WeakMap;
>   this.bindContext = bindContext;
>   return bindContext.call(this, context);
>   function bindContext(context) {
> if (!_.has(context))
>   _.set(context, this.bind(context));
> return _.get(context);
>   }
> };
> ```
>
> # Implementation details
>
> As the method suggest, and differently from `bind`, `bindContext` accepts
> only one argument, and it should throw with any context that is primitive
> (boolean, number, string, undefined, null), like any WeakMap key would
> throw as well.
>
> # Why not user-land / libraries / helpers
>
> Because standardizing a well-known/needed utility to not footgun common
> patterns would make the debate regarding global prototypes pollution
> irrelevant, as it's the standard that helps us out.
>
> In a few words, this might erase tons of common mistakes, but it also
> could be simplified within some helper/library, as long as not all of them
> need to include the proposed polyfill through a package or another.
>
> Thanks for consideration 👋
>
> ___
> 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


Proposal: Function.prototype.bindContext

2020-09-17 Thread Andrea Giammarchi
I've found myself (once again) polluting the `Function.prototype` with a
lazy method that, once invoked, grants that the returned bound function is
always the same, per context.

# Use Case

It's still a common footgun to add events either via `context.method` or
via `context.method.bind(context)`, where the former footgan would invoke
`method` with a global context/undefined instead of the expected context,
while the latter would make it impossible to ever remove that listener
later on.

It's also common to use methods for timers sensitive things, and it's
indeed not by accident that `console` got "self bound", or provided as
namespace, when it used to throw if `setTimeout(console.log, 100, value)`
was used, for example.

# Proposal

Provide a lazy `bindContext` method that grants that if a method/function
bound the same context before, it always returns the same reference.

# Implementation / Polyfill (lazy version)

```js
Function.prototype.bindContext = function (context) {
  const _ = new WeakMap;
  this.bindContext = bindContext;
  return bindContext.call(this, context);
  function bindContext(context) {
if (!_.has(context))
  _.set(context, this.bind(context));
return _.get(context);
  }
};
```

# Implementation details

As the method suggest, and differently from `bind`, `bindContext` accepts
only one argument, and it should throw with any context that is primitive
(boolean, number, string, undefined, null), like any WeakMap key would
throw as well.

# Why not user-land / libraries / helpers

Because standardizing a well-known/needed utility to not footgun common
patterns would make the debate regarding global prototypes pollution
irrelevant, as it's the standard that helps us out.

In a few words, this might erase tons of common mistakes, but it also could
be simplified within some helper/library, as long as not all of them need
to include the proposed polyfill through a package or another.

Thanks for consideration 👋
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Since JSDoc seems cerebrally dead...

2020-08-17 Thread Andrea Giammarchi
Sorry, new link:
https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html

On Mon, Aug 17, 2020 at 8:34 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> TS supports JSDocs already
>
> https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#supported-jsdoc
>
> On Mon, Aug 17, 2020 at 8:31 PM Bergi  wrote:
>
>> Hi,
>>
>> > They don't want to add TS to their stack.
>>
>> Then what else would they want to add to their stack? Notice one doesn't
>> necessarily need the TypeScript Compiler to add TypeScript- or Flow-like
>> type annotations and remove them in a build step - Babel for example
>> could do that just fine as well.
>> Or are you asking for a jsdoc-like thing that lives in comments, where
>> the code can be run without a compilation step?
>>
>> kind regards,
>>  Bergi
>> ___
>> 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: Since JSDoc seems cerebrally dead...

2020-08-17 Thread Andrea Giammarchi
TS supports JSDocs already
https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#supported-jsdoc

On Mon, Aug 17, 2020 at 8:31 PM Bergi  wrote:

> Hi,
>
> > They don't want to add TS to their stack.
>
> Then what else would they want to add to their stack? Notice one doesn't
> necessarily need the TypeScript Compiler to add TypeScript- or Flow-like
> type annotations and remove them in a build step - Babel for example
> could do that just fine as well.
> Or are you asking for a jsdoc-like thing that lives in comments, where
> the code can be run without a compilation step?
>
> kind regards,
>  Bergi
> ___
> 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: Why aren't interpolation values in tagged template calls saved as a cached array?

2020-07-26 Thread Andrea Giammarchi
there is some fundamental misconception of the ECMAScript standard in these
examples ... to start with, assuming the same `arguments` object is passed
twice to two different invokes of a callback, would break down to ES3 and
lower.

Secondly, interpolated values you are passing around are always different,
so I can't understand why would you expect an always same Array in there
... it's not the same as the template one, which is immutable, aka frozen,
and it can carry any different value at any different position.

Accordingly, the current standard for template literals tags function is
nearly perfect, and none of these suggestions would improve anything in the
wild (using template literals since 2015, I think I've consumed them all in
all flavours).

Regards.

On Sun, Jul 26, 2020 at 8:08 PM #!/JoePea  wrote:

> The following doesn't work either, and obviously it probably will
> never change because it is historical:
>
> ```js
> argsArrays = []
>
> function html() {
> argsArrays.push(arguments)
> }
>
> let n = 0
> let n2 = 0
>
> function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
>
> render()
> render()
>
> console.log(argsArrays[0] === argsArrays[1]) // false!
> ```
>
> So yeah, just wondering why our only option is to use `...args` and
> create new arrays each time, thus the performance is not optimized
> like it is with the string parts.
>
> #!/JoePea
>
> On Sun, Jul 26, 2020 at 10:49 AM #!/JoePea  wrote:
> >
> > What I mean is,
> >
> > We can currently do this (try it in console):
> >
> > ```js
> > arrays = []
> >
> > function html(parts) { arrays.push(parts) }
> >
> > let n = 0
> > let n2 = 0
> >
> > function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
> >
> > render()
> > render()
> >
> > console.log(arrays[0] === arrays[1]) // true! <--- This!
> > ```
> >
> > But why don't specs allows us to do the following as well? (don't run
> > it, it doesn't work as intended)
> >
> > ```js
> > partsArrays = []
> > valuesArrays = []
> >
> > function html(parts, values) {
> > partsArrays.push(parts)
> > valuesArrays.push(values)
> > }
> >
> > let n = 0
> > let n2 = 0
> >
> > function render() { return html`1st: ${n++}, 2nd: ${n2++}.` }
> >
> > render()
> > render()
> >
> > console.log(partsArrays[0] === partsArrays[1]) // true!
> > console.log(valuesArrays[0] === valuesArrays[1]) // This would be
> > convenient too! I think?
> > ```
> >
> > Instead, if we want an array of the values, we have to use `arguments`
> > or `...args`. For example:
> >
> > ```js
> > // ... same ...
> > function html(parts, ...values) {
> > partsArrays.push(parts)
> > valuesArrays.push(values)
> > }
> > // ... same ...
> > console.log(partsArrays[0] === partsArrays[1]) // true!
> > console.log(valuesArrays[0] === valuesArrays[1]) // false! New array
> every time.
> > ```
> >
> > Seems like it would've been great to have the cached values arrays
> > too. Why isn't this the case?
> >
> > #!/JoePea
> ___
> 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: Are ES Modules garbage collected? If so, do they re-execute on next import?

2020-07-16 Thread Andrea Giammarchi
On a second thought ... couldn't `import.meta.cache`, or something similar,
be implemented in NodeJS only?

On Thu, Jul 16, 2020 at 3:44 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> FWIW explicit eviction is not only fine, if you own the code that does
> that, but the only way I can code cover 100% all the branches of my
> libraries. The issue here is the untrusted Web, where I'd never expect any
> 3rd parts library to evict a module I am using within my code ... like ...
> ever.
>
> Accordingly, I think Allen, if it was Allen, made the right call for ESM.
>
> On Thu, Jul 16, 2020 at 3:23 PM Guy Bedford  wrote:
>
>> Node.js in the CommonJS loader and dynamic loaders like SystemJS have
>> supported module unloading for many years by permitting eviction from the
>> loader registry. Evicting the full parent tree was the traditional
>> reloading workflow in SystemJS, but live binding pushes are also permitted
>> in SystemJS as well for this.
>>
>> I agree there are issues and invariants of course to consider from a
>> theoretical perspective, but those are decisions to be made in terms of
>> what invariants are valued, and I don't feel they are necessarily absolute
>> constraints. These decisions should be made based on what is best for
>> the JS users and engines. Not that I feel strongly this should be a
>> requirement but that it should still be open to consideration.
>>
>> I'm not sure it was Allen's intention to ban any concept of reloading
>> modules when defining the idempotency requirement for the host resolve
>> function. Perhaps he could speak to that if he's around.
>>
>>
>> On Tue, 14 Jul 2020 at 23:05, Mark S. Miller  wrote:
>>
>>> Only a module registry as a whole may be GCed. During the lifetime of
>>> any one module registry, it can only grow. No other solution is possible.
>>>
>>> Btw, I remember being surprised ages ago when the same issue came up for
>>> the Java ClassLoader. A classLoader holds on to all the classes it ever
>>> loaded. Each class holds onto its classLoader. Each instance holds on to
>>> its class. During the lifetime of a classLoader or any of its classes, the
>>> graph of that classLoader and its classes can only grow new classes. Not
>>> until the classLoader and all of its classes are unreachable at the same
>>> time can any of them be collected. This was equally unfortunate,
>>> surprising, and inescapable.
>>>
>>>
>>>
>>> On Tue, Jul 14, 2020 at 10:16 PM #!/JoePea  wrote:
>>>
>>>> How can we ensure that long-running applications (even if theoretical),
>>>> that may load and unload an unlimited number of new modules over time
>>>> (f.e. routes in a web page specified by 3rd parties as time
>>>> progresses), not leak memory?
>>>>
>>>> Even if it is theoretical, I don't like the thought of something that
>>>> only ever allocates memory that will never be freed.
>>>>
>>>> Is someone working on a solution for this?
>>>>
>>>>
>>>> #!/JoePea
>>>>
>>>> On Wed, Jul 1, 2020 at 6:16 AM Mark S. Miller 
>>>> wrote:
>>>> >
>>>> > No, definitely not. The table from specifiers to module instances is
>>>> indexed by specifiers. Specifiers are strings, so this table is not weak.
>>>> It is not a "cache" in the sense that it is allowed to drop things. Rather
>>>> it is a registry of module instances. Only a registry as a whole can be
>>>> gc'ed, and which point that context is no longer around for instantiating
>>>> or reinstantiating modules.
>>>> >
>>>> > As you suggest, if it could drop things because of GC that it would
>>>> then need to regenerate, that would expose the non-determinism of gc. That
>>>> would be a big deal. We carefully designed WeakMaps so that gc was
>>>> non-observable. WeakMaps introduce no observable non-determinism. WeakRefs
>>>> alone expose the non-determinism of gc, and are kept well quarantined from
>>>> the rest of the language.
>>>> >
>>>> >
>>>> > On Tue, Jun 30, 2020 at 5:42 PM #!/JoePea  wrote:
>>>> >>
>>>> >> I am curious: can modules be garbage collected if the exports are not
>>>> >> references by anything anymore? And if so, will the module be
>>>> >> re-evaluated the next time it is imported?
>>>> >>

Re: Are ES Modules garbage collected? If so, do they re-execute on next import?

2020-07-16 Thread Andrea Giammarchi
FWIW explicit eviction is not only fine, if you own the code that does
that, but the only way I can code cover 100% all the branches of my
libraries. The issue here is the untrusted Web, where I'd never expect any
3rd parts library to evict a module I am using within my code ... like ...
ever.

Accordingly, I think Allen, if it was Allen, made the right call for ESM.

On Thu, Jul 16, 2020 at 3:23 PM Guy Bedford  wrote:

> Node.js in the CommonJS loader and dynamic loaders like SystemJS have
> supported module unloading for many years by permitting eviction from the
> loader registry. Evicting the full parent tree was the traditional
> reloading workflow in SystemJS, but live binding pushes are also permitted
> in SystemJS as well for this.
>
> I agree there are issues and invariants of course to consider from a
> theoretical perspective, but those are decisions to be made in terms of
> what invariants are valued, and I don't feel they are necessarily absolute
> constraints. These decisions should be made based on what is best for
> the JS users and engines. Not that I feel strongly this should be a
> requirement but that it should still be open to consideration.
>
> I'm not sure it was Allen's intention to ban any concept of reloading
> modules when defining the idempotency requirement for the host resolve
> function. Perhaps he could speak to that if he's around.
>
>
> On Tue, 14 Jul 2020 at 23:05, Mark S. Miller  wrote:
>
>> Only a module registry as a whole may be GCed. During the lifetime of any
>> one module registry, it can only grow. No other solution is possible.
>>
>> Btw, I remember being surprised ages ago when the same issue came up for
>> the Java ClassLoader. A classLoader holds on to all the classes it ever
>> loaded. Each class holds onto its classLoader. Each instance holds on to
>> its class. During the lifetime of a classLoader or any of its classes, the
>> graph of that classLoader and its classes can only grow new classes. Not
>> until the classLoader and all of its classes are unreachable at the same
>> time can any of them be collected. This was equally unfortunate,
>> surprising, and inescapable.
>>
>>
>>
>> On Tue, Jul 14, 2020 at 10:16 PM #!/JoePea  wrote:
>>
>>> How can we ensure that long-running applications (even if theoretical),
>>> that may load and unload an unlimited number of new modules over time
>>> (f.e. routes in a web page specified by 3rd parties as time
>>> progresses), not leak memory?
>>>
>>> Even if it is theoretical, I don't like the thought of something that
>>> only ever allocates memory that will never be freed.
>>>
>>> Is someone working on a solution for this?
>>>
>>>
>>> #!/JoePea
>>>
>>> On Wed, Jul 1, 2020 at 6:16 AM Mark S. Miller  wrote:
>>> >
>>> > No, definitely not. The table from specifiers to module instances is
>>> indexed by specifiers. Specifiers are strings, so this table is not weak.
>>> It is not a "cache" in the sense that it is allowed to drop things. Rather
>>> it is a registry of module instances. Only a registry as a whole can be
>>> gc'ed, and which point that context is no longer around for instantiating
>>> or reinstantiating modules.
>>> >
>>> > As you suggest, if it could drop things because of GC that it would
>>> then need to regenerate, that would expose the non-determinism of gc. That
>>> would be a big deal. We carefully designed WeakMaps so that gc was
>>> non-observable. WeakMaps introduce no observable non-determinism. WeakRefs
>>> alone expose the non-determinism of gc, and are kept well quarantined from
>>> the rest of the language.
>>> >
>>> >
>>> > On Tue, Jun 30, 2020 at 5:42 PM #!/JoePea  wrote:
>>> >>
>>> >> I am curious: can modules be garbage collected if the exports are not
>>> >> references by anything anymore? And if so, will the module be
>>> >> re-evaluated the next time it is imported?
>>> >>
>>> >> I haven't tried an experiment to answer this yet. I'll be back to post
>>> >> findings if someone doesn't post an official answer first.
>>> >>
>>> >> I'm thinking about code longevity. For example, if we make
>>> >> long-running web-based applications with many routes and features (for
>>> >> sake of example imagine a desktop environment, or a MMORPG game, with
>>> >> apps or components that are loaded within the same context). Over
>>> >> time, if imports are not collected, then it means we have a memory
>>> >> leak.
>>> >>
>>> >> Imagine, for example, an infinite-universe MMORPG where you can land
>>> >> on different planets where the code for features of a planet are
>>> >> provided by third parties as ES Modules. I know, this might not be a
>>> >> safe idea to import any code into an app, but just imagine it for sake
>>> >> of example (imagine we have a continuous integration system to test
>>> >> and verify code security, or something, before that code is allowed to
>>> >> be consumed in the app). Imagine you play this app for many many days,
>>> >> and visit many places, and you leave the app running the w

Re: Are ES Modules garbage collected? If so, do they re-execute on next import?

2020-06-30 Thread Andrea Giammarchi
even if dereferenced, a dynamic import could re-reference it any time, and
I would expect it to still be the same module, it'd be a surprise otherwise
(cached things, same namespace checks, etc).

On Wed, Jul 1, 2020 at 7:33 AM Isiah Meadows 
wrote:

> Just to expand on that, if the module record itself is dereferenced
> (like if it's evicted from the cache somehow), then yes, it should be
> collected as appropriate. However, I'm not aware of any major
> implementation that offers that functionality.
>
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
>
> On Tue, Jun 30, 2020 at 6:22 PM Gus Caplan  wrote:
> >
> > Modules in the spec are cached by specifier by modules that import them.
> Modules in major implementations are additionally cached for the entire
> realm by absolute URLs. I would say that for actual code (functions and
> classes and whatnot) leaks aren't really a problem. Even if you import a
> ton of levels, that's not that much memory. The main concern I've seen
> raised is JSON modules, where once you import them the JSON object, which
> can be quite large, will never be collected. Of course, there is a simple
> solution to that (fetch) so it isn't a world ending problem.
> >
> > On Tue, Jun 30, 2020 at 7:41 PM #!/JoePea  wrote:
> >>
> >> I am curious: can modules be garbage collected if the exports are not
> >> references by anything anymore? And if so, will the module be
> >> re-evaluated the next time it is imported?
> >>
> >> I haven't tried an experiment to answer this yet. I'll be back to post
> >> findings if someone doesn't post an official answer first.
> >>
> >> I'm thinking about code longevity. For example, if we make
> >> long-running web-based applications with many routes and features (for
> >> sake of example imagine a desktop environment, or a MMORPG game, with
> >> apps or components that are loaded within the same context). Over
> >> time, if imports are not collected, then it means we have a memory
> >> leak.
> >>
> >> Imagine, for example, an infinite-universe MMORPG where you can land
> >> on different planets where the code for features of a planet are
> >> provided by third parties as ES Modules. I know, this might not be a
> >> safe idea to import any code into an app, but just imagine it for sake
> >> of example (imagine we have a continuous integration system to test
> >> and verify code security, or something, before that code is allowed to
> >> be consumed in the app). Imagine you play this app for many many days,
> >> and visit many places, and you leave the app running the whole time
> >> (because farming for resources is disabled if the app is not running,
> >> or something).
> >>
> >> I would imagine that we want unused modules (when we leave a planet,
> >> for example) to be (destroyed) garbage collected so that we don't
> >> waste memory.
> >>
> >> #!/JoePea
> >> ___
> >> 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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A Function.tag proposal?

2020-06-22 Thread Andrea Giammarchi
I think it doesn't matter where it lands, and I've overlooked at the
already available String.raw.

My idea is to have it "no matter where, or how named" as it's the
functionality I am after, not the name.

String.plain sounds great, but since template literals tag functions are
named "template literals tag functions", I've thought String.tag would
implicitly describe the intent.

And then again, I don't care about the name, "we" (developers that use
template literals a lot) would love it no matter how it's called ;-)

On Mon, Jun 22, 2020 at 7:16 PM Bergi  wrote:

> Hi Andrea,
>
> my 5ct: Putting the static function on the `Function` object doesn't
> make any sense to me. Using `String.tag` seems like much more sensible
> choice. Or, how about `String.plain`, in contrast to `String.raw`?
>
> I can see the use case, altough I'd really prefer tooling to become more
> intelligent in that regard.
>
> best,
>  Bergi
> ___
> 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: A Function.tag proposal?

2020-06-22 Thread Andrea Giammarchi
btw, in case somebody reads this issue, this is the current workaround:

```js
const tag = (raw, ...values) => String.raw({raw}, ...values);
```

it's still better than my dummy tag (hopefully at least on performance),
but as it's becoming more common than ever, it'd be great to have
`String.tag` doing exactly that.

Best Regards


On Mon, Jun 22, 2020 at 2:30 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> It doesn't work. There's been a lengthy discussion here
> https://github.com/mjbvz/vscode-lit-html/issues/14 and comments are not
> welcome in most tools, but even GitHub fails at highlighting the string,
> and no intellisense works within comments.
>
> The simplest request considered as "increased JS complexity" also feels a
> bit of an exaggeration: there are various use cases, and I wouldn't have
> proposed this if useless.
>
> Although, `String.tag` instead of `String.raw` seems like a welcome
> compromise, actually even more semantic, so the proposal would be to add a
> tag that does exactly what `String.raw` does without escaping sequences.
>
> As there is already an identical function that is a footgun for the
> described use-case, I don't see any extra complexity in having `String.tag`.
>
> Best Regards.
>
> On Mon, Jun 22, 2020 at 2:00 PM Bruno Macabeus 
> wrote:
>
>> You could just use comments in order to provide metainformations to your
>> developer tools instead of adding a new feature on language.
>>
>> const style = /*css*/`
>>   body {
>> color: green;
>>   }
>> `;
>>
>> const node = /*html*/`
>>   hello world
>> `;
>>
>> Or an even better solution is change your highlight to firstly try to match 
>> a HTML, if fail try to match CSS, if fail match as a plain string.
>>
>> IMHO it isn't necessary to increase the complexity of JS to do that.
>>
>>
>> On Mon, 22 Jun 2020 at 12:02, François REMY <
>> francois.remy@outlook.com> wrote:
>>
>>> What exactly are you proposing to do differently than String.raw?
>>>
>>>
>>> https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/string/raw
>>>
>>> Sent from my phone
>>> --
>>> *From:* es-discuss  on behalf of Andrea
>>> Giammarchi 
>>> *Sent:* Monday, June 22, 2020 12:24:13 PM
>>> *To:* es-discuss@mozilla.org 
>>> *Subject:* A Function.tag proposal?
>>>
>>> This is something somehow bothering developers and tools, sooner or
>>> later, the need for a no-op template literal tag function that just returns
>>> the string as is.
>>>
>>> The current workaround to have highlights, proper content minification,
>>> etc, is the following one:
>>>
>>> ```js
>>>
>>> import css from 'dummy-tag';import html from 'dummy-tag';
>>> const style = css`  body {color: green;  }`;
>>> const node = html`  hello world`;
>>>
>>> ```
>>>
>>> but as irrelevant as the dummy-tag code is, in size, it's a dependency,
>>> and a function that can't get easily optimized, due the nature of the tag
>>> signature.
>>>
>>> ### Proposal
>>>
>>> Provide a static `Function.tag` which internally flattens out any
>>> template literal content.
>>>
>>> ```js
>>>
>>> const css = Function.tag;
>>> const html = Function.tag;
>>>
>>> const style = css`  body {color: green;  }`;
>>> const node = html`  hello world`;
>>>
>>> ```
>>>
>>> Internally it will place eventual interpolations within template chunks,
>>> and return a string.
>>>
>>> ```js
>>> Function.tag`1${2}3` === '123';
>>> ```
>>>
>>> That's it. Thoughts?
>>>
>>> Best Regards
>>>
>>>
>>>
>>> ___
>>> 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: A Function.tag proposal?

2020-06-22 Thread Andrea Giammarchi
It doesn't work. There's been a lengthy discussion here
https://github.com/mjbvz/vscode-lit-html/issues/14 and comments are not
welcome in most tools, but even GitHub fails at highlighting the string,
and no intellisense works within comments.

The simplest request considered as "increased JS complexity" also feels a
bit of an exaggeration: there are various use cases, and I wouldn't have
proposed this if useless.

Although, `String.tag` instead of `String.raw` seems like a welcome
compromise, actually even more semantic, so the proposal would be to add a
tag that does exactly what `String.raw` does without escaping sequences.

As there is already an identical function that is a footgun for the
described use-case, I don't see any extra complexity in having `String.tag`.

Best Regards.

On Mon, Jun 22, 2020 at 2:00 PM Bruno Macabeus 
wrote:

> You could just use comments in order to provide metainformations to your
> developer tools instead of adding a new feature on language.
>
> const style = /*css*/`
>   body {
> color: green;
>   }
> `;
>
> const node = /*html*/`
>   hello world
> `;
>
> Or an even better solution is change your highlight to firstly try to match a 
> HTML, if fail try to match CSS, if fail match as a plain string.
>
> IMHO it isn't necessary to increase the complexity of JS to do that.
>
>
> On Mon, 22 Jun 2020 at 12:02, François REMY 
> wrote:
>
>> What exactly are you proposing to do differently than String.raw?
>>
>>
>> https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/string/raw
>>
>> Sent from my phone
>> --
>> *From:* es-discuss  on behalf of Andrea
>> Giammarchi 
>> *Sent:* Monday, June 22, 2020 12:24:13 PM
>> *To:* es-discuss@mozilla.org 
>> *Subject:* A Function.tag proposal?
>>
>> This is something somehow bothering developers and tools, sooner or
>> later, the need for a no-op template literal tag function that just returns
>> the string as is.
>>
>> The current workaround to have highlights, proper content minification,
>> etc, is the following one:
>>
>> ```js
>>
>> import css from 'dummy-tag';import html from 'dummy-tag';
>> const style = css`  body {color: green;  }`;
>> const node = html`  hello world`;
>>
>> ```
>>
>> but as irrelevant as the dummy-tag code is, in size, it's a dependency,
>> and a function that can't get easily optimized, due the nature of the tag
>> signature.
>>
>> ### Proposal
>>
>> Provide a static `Function.tag` which internally flattens out any
>> template literal content.
>>
>> ```js
>>
>> const css = Function.tag;
>> const html = Function.tag;
>>
>> const style = css`  body {color: green;  }`;
>> const node = html`  hello world`;
>>
>> ```
>>
>> Internally it will place eventual interpolations within template chunks,
>> and return a string.
>>
>> ```js
>> Function.tag`1${2}3` === '123';
>> ```
>>
>> That's it. Thoughts?
>>
>> Best Regards
>>
>>
>>
>> ___
>> 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: A Function.tag proposal?

2020-06-22 Thread Andrea Giammarchi
That is not raw.

On Mon, Jun 22, 2020 at 1:02 PM François REMY 
wrote:

> What exactly are you proposing to do differently than String.raw?
>
>
> https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/string/raw
>
> Sent from my phone
> --
> *From:* es-discuss  on behalf of Andrea
> Giammarchi 
> *Sent:* Monday, June 22, 2020 12:24:13 PM
> *To:* es-discuss@mozilla.org 
> *Subject:* A Function.tag proposal?
>
> This is something somehow bothering developers and tools, sooner or later,
> the need for a no-op template literal tag function that just returns the
> string as is.
>
> The current workaround to have highlights, proper content minification,
> etc, is the following one:
>
> ```js
>
> import css from 'dummy-tag';import html from 'dummy-tag';
> const style = css`  body {color: green;  }`;
> const node = html`  hello world`;
>
> ```
>
> but as irrelevant as the dummy-tag code is, in size, it's a dependency,
> and a function that can't get easily optimized, due the nature of the tag
> signature.
>
> ### Proposal
>
> Provide a static `Function.tag` which internally flattens out any template
> literal content.
>
> ```js
>
> const css = Function.tag;
> const html = Function.tag;
>
> const style = css`  body {color: green;  }`;
> const node = html`  hello world`;
>
> ```
>
> Internally it will place eventual interpolations within template chunks,
> and return a string.
>
> ```js
> Function.tag`1${2}3` === '123';
> ```
>
> That's it. Thoughts?
>
> Best Regards
>
>
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


A Function.tag proposal?

2020-06-22 Thread Andrea Giammarchi
This is something somehow bothering developers and tools, sooner or later,
the need for a no-op template literal tag function that just returns the
string as is.

The current workaround to have highlights, proper content minification,
etc, is the following one:

```js

import css from 'dummy-tag';import html from 'dummy-tag';
const style = css`  body {color: green;  }`;
const node = html`  hello world`;

```

but as irrelevant as the dummy-tag code is, in size, it's a dependency, and
a function that can't get easily optimized, due the nature of the tag
signature.

### Proposal

Provide a static `Function.tag` which internally flattens out any template
literal content.

```js

const css = Function.tag;
const html = Function.tag;

const style = css`  body {color: green;  }`;
const node = html`  hello world`;

```

Internally it will place eventual interpolations within template chunks,
and return a string.

```js
Function.tag`1${2}3` === '123';
```

That's it. Thoughts?

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


Re: Any chance for an `Object.assignProperties` ?

2020-02-13 Thread Andrea Giammarchi
Anyway, if anyone is interested, I've published the `assign-properties`
module [1]

[1] https://github.com/WebReflection/assign-properties#readme

On Thu, Feb 13, 2020 at 7:51 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> The fact `assign` doesn't copy descriptors and has potential side-effects
> is documented extensively though, meaning there is room for improvement, or
> simply a missing native way to do that, like it was for
> `getOwnPropertyDescriptors`, that following your logic should've never
> landed.
>
> But I guess I'd go with the usual "yet another micro library" approach
> instead, so that at least I won't have to deal with assign shenanigans when
> I mean to copy accessors too.
>
> On Thu, Feb 13, 2020 at 7:33 PM Jordan Harband  wrote:
>
>> It seems like it’s the exact implementation you want, just for 1 object
>> instead of N.
>>
>> Object.assign was added because versions of it were all over the web,
>> used very frequently. How frequent is the pattern where people want to copy
>> descriptors, such that it would deserve reification in the language?
>>
>> On Thu, Feb 13, 2020 at 10:23 AM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> That has nothing to do with this, right?
>>>
>>> ```js
>>> const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
>>> const assignProperties = (base, ...mixins) => defineProperties(
>>>   base,
>>>   mixins.reduce(
>>> (descriptors, mixin) => assign(
>>>   descriptors,
>>>   getOwnPropertyDescriptors(mixin)
>>> ),
>>> {}
>>>   )
>>> );
>>> ```
>>>
>>> On Thu, Feb 13, 2020 at 6:51 PM Jordan Harband  wrote:
>>>
>>>> `Object.defineProperties(target,
>>>> Object.getOwnPropertyDescriptors(source))`?
>>>>
>>>> On Thu, Feb 13, 2020 at 2:24 AM Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> Both `Object.assign` and `{...extend}` suffer a tiny gotcha:
>>>>> properties are never assigned, neither retrieved, as accessors, with
>>>>> side-effects too.
>>>>>
>>>>> Example:
>>>>> ```js
>>>>> const Counter = {
>>>>>   _count: 0,
>>>>>   get count() {
>>>>> return this._count++;
>>>>>   }
>>>>> };
>>>>>
>>>>> const incr1 = Object.assign({}, Counter);
>>>>> const incr2 = {...Counter};
>>>>>
>>>>> console.log(
>>>>>   incr1.count,// 0
>>>>>   incr2.count,// 1
>>>>>   Counter._count  // 2
>>>>> );
>>>>>
>>>>> // functionality also compromised
>>>>> console.log(incr1.count === incr1.count);
>>>>> ```
>>>>>
>>>>> Not only most of the time this is unexpected, but there's literally no
>>>>> way to pass along accessors with a similar `Object.assign` ease, even if
>>>>> that's what most developers would expect (at least up to the first time
>>>>> they encounter above issue).
>>>>>
>>>>> How about we introduce `Object.assignProperties` instead?
>>>>>
>>>>> A polyfill example:
>>>>>
>>>>> ```js
>>>>> const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
>>>>> const assignProperties = (base, ...mixins) => defineProperties(
>>>>>   base,
>>>>>   mixins.reduce(
>>>>> (descriptors, mixin) => assign(
>>>>>   descriptors,
>>>>>   getOwnPropertyDescriptors(mixin)
>>>>> ),
>>>>> {}
>>>>>   )
>>>>> );
>>>>> ```
>>>>>
>>>>> We can now use objects and mixins without side-effecting sources used
>>>>> to extend, and preserving accessors in the process.
>>>>>
>>>>> ```js
>>>>> const Counter = {
>>>>>   _count: 0,
>>>>>   get count() {
>>>>> return this._count++;
>>>>>   }
>>>>> };
>>>>>
>>>>> const incr1 = Object.assignProperties({}, Counter);
>>>>> const incr2 = Object.assignProperties({}, Counter);
>>>>>
>>>>> console.log(
>>>>>   incr1.count,// 0
>>>>>   incr2.count,// 0
>>>>>   Counter._count  // 0
>>>>> );
>>>>>
>>>>> // always false: preserved functionality
>>>>> console.log(incr1.count === incr1.count);
>>>>> ```
>>>>>
>>>>> Thoughts ?
>>>>> ___
>>>>> 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: Any chance for an `Object.assignProperties` ?

2020-02-13 Thread Andrea Giammarchi
The fact `assign` doesn't copy descriptors and has potential side-effects
is documented extensively though, meaning there is room for improvement, or
simply a missing native way to do that, like it was for
`getOwnPropertyDescriptors`, that following your logic should've never
landed.

But I guess I'd go with the usual "yet another micro library" approach
instead, so that at least I won't have to deal with assign shenanigans when
I mean to copy accessors too.

On Thu, Feb 13, 2020 at 7:33 PM Jordan Harband  wrote:

> It seems like it’s the exact implementation you want, just for 1 object
> instead of N.
>
> Object.assign was added because versions of it were all over the web, used
> very frequently. How frequent is the pattern where people want to copy
> descriptors, such that it would deserve reification in the language?
>
> On Thu, Feb 13, 2020 at 10:23 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> That has nothing to do with this, right?
>>
>> ```js
>> const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
>> const assignProperties = (base, ...mixins) => defineProperties(
>>   base,
>>   mixins.reduce(
>> (descriptors, mixin) => assign(
>>   descriptors,
>>   getOwnPropertyDescriptors(mixin)
>> ),
>> {}
>>   )
>> );
>> ```
>>
>> On Thu, Feb 13, 2020 at 6:51 PM Jordan Harband  wrote:
>>
>>> `Object.defineProperties(target,
>>> Object.getOwnPropertyDescriptors(source))`?
>>>
>>> On Thu, Feb 13, 2020 at 2:24 AM Andrea Giammarchi <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> Both `Object.assign` and `{...extend}` suffer a tiny gotcha: properties
>>>> are never assigned, neither retrieved, as accessors, with side-effects too.
>>>>
>>>> Example:
>>>> ```js
>>>> const Counter = {
>>>>   _count: 0,
>>>>   get count() {
>>>> return this._count++;
>>>>   }
>>>> };
>>>>
>>>> const incr1 = Object.assign({}, Counter);
>>>> const incr2 = {...Counter};
>>>>
>>>> console.log(
>>>>   incr1.count,// 0
>>>>   incr2.count,// 1
>>>>   Counter._count  // 2
>>>> );
>>>>
>>>> // functionality also compromised
>>>> console.log(incr1.count === incr1.count);
>>>> ```
>>>>
>>>> Not only most of the time this is unexpected, but there's literally no
>>>> way to pass along accessors with a similar `Object.assign` ease, even if
>>>> that's what most developers would expect (at least up to the first time
>>>> they encounter above issue).
>>>>
>>>> How about we introduce `Object.assignProperties` instead?
>>>>
>>>> A polyfill example:
>>>>
>>>> ```js
>>>> const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
>>>> const assignProperties = (base, ...mixins) => defineProperties(
>>>>   base,
>>>>   mixins.reduce(
>>>> (descriptors, mixin) => assign(
>>>>   descriptors,
>>>>   getOwnPropertyDescriptors(mixin)
>>>> ),
>>>> {}
>>>>   )
>>>> );
>>>> ```
>>>>
>>>> We can now use objects and mixins without side-effecting sources used
>>>> to extend, and preserving accessors in the process.
>>>>
>>>> ```js
>>>> const Counter = {
>>>>   _count: 0,
>>>>   get count() {
>>>> return this._count++;
>>>>   }
>>>> };
>>>>
>>>> const incr1 = Object.assignProperties({}, Counter);
>>>> const incr2 = Object.assignProperties({}, Counter);
>>>>
>>>> console.log(
>>>>   incr1.count,// 0
>>>>   incr2.count,// 0
>>>>   Counter._count  // 0
>>>> );
>>>>
>>>> // always false: preserved functionality
>>>> console.log(incr1.count === incr1.count);
>>>> ```
>>>>
>>>> Thoughts ?
>>>> ___
>>>> 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: Any chance for an `Object.assignProperties` ?

2020-02-13 Thread Andrea Giammarchi
That has nothing to do with this, right?

```js
const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
const assignProperties = (base, ...mixins) => defineProperties(
  base,
  mixins.reduce(
(descriptors, mixin) => assign(
  descriptors,
  getOwnPropertyDescriptors(mixin)
),
{}
  )
);
```

On Thu, Feb 13, 2020 at 6:51 PM Jordan Harband  wrote:

> `Object.defineProperties(target,
> Object.getOwnPropertyDescriptors(source))`?
>
> On Thu, Feb 13, 2020 at 2:24 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> Both `Object.assign` and `{...extend}` suffer a tiny gotcha: properties
>> are never assigned, neither retrieved, as accessors, with side-effects too.
>>
>> Example:
>> ```js
>> const Counter = {
>>   _count: 0,
>>   get count() {
>> return this._count++;
>>   }
>> };
>>
>> const incr1 = Object.assign({}, Counter);
>> const incr2 = {...Counter};
>>
>> console.log(
>>   incr1.count,// 0
>>   incr2.count,// 1
>>   Counter._count  // 2
>> );
>>
>> // functionality also compromised
>> console.log(incr1.count === incr1.count);
>> ```
>>
>> Not only most of the time this is unexpected, but there's literally no
>> way to pass along accessors with a similar `Object.assign` ease, even if
>> that's what most developers would expect (at least up to the first time
>> they encounter above issue).
>>
>> How about we introduce `Object.assignProperties` instead?
>>
>> A polyfill example:
>>
>> ```js
>> const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
>> const assignProperties = (base, ...mixins) => defineProperties(
>>   base,
>>   mixins.reduce(
>> (descriptors, mixin) => assign(
>>   descriptors,
>>   getOwnPropertyDescriptors(mixin)
>> ),
>> {}
>>   )
>> );
>> ```
>>
>> We can now use objects and mixins without side-effecting sources used to
>> extend, and preserving accessors in the process.
>>
>> ```js
>> const Counter = {
>>   _count: 0,
>>   get count() {
>> return this._count++;
>>   }
>> };
>>
>> const incr1 = Object.assignProperties({}, Counter);
>> const incr2 = Object.assignProperties({}, Counter);
>>
>> console.log(
>>   incr1.count,// 0
>>   incr2.count,// 0
>>   Counter._count  // 0
>> );
>>
>> // always false: preserved functionality
>> console.log(incr1.count === incr1.count);
>> ```
>>
>> Thoughts ?
>> ___
>> 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


Any chance for an `Object.assignProperties` ?

2020-02-13 Thread Andrea Giammarchi
Both `Object.assign` and `{...extend}` suffer a tiny gotcha: properties are
never assigned, neither retrieved, as accessors, with side-effects too.

Example:
```js
const Counter = {
  _count: 0,
  get count() {
return this._count++;
  }
};

const incr1 = Object.assign({}, Counter);
const incr2 = {...Counter};

console.log(
  incr1.count,// 0
  incr2.count,// 1
  Counter._count  // 2
);

// functionality also compromised
console.log(incr1.count === incr1.count);
```

Not only most of the time this is unexpected, but there's literally no way
to pass along accessors with a similar `Object.assign` ease, even if that's
what most developers would expect (at least up to the first time they
encounter above issue).

How about we introduce `Object.assignProperties` instead?

A polyfill example:

```js
const {assign, defineProperties, getOwnPropertyDescriptors} = Object;
const assignProperties = (base, ...mixins) => defineProperties(
  base,
  mixins.reduce(
(descriptors, mixin) => assign(
  descriptors,
  getOwnPropertyDescriptors(mixin)
),
{}
  )
);
```

We can now use objects and mixins without side-effecting sources used to
extend, and preserving accessors in the process.

```js
const Counter = {
  _count: 0,
  get count() {
return this._count++;
  }
};

const incr1 = Object.assignProperties({}, Counter);
const incr2 = Object.assignProperties({}, Counter);

console.log(
  incr1.count,// 0
  incr2.count,// 0
  Counter._count  // 0
);

// always false: preserved functionality
console.log(incr1.count === incr1.count);
```

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


Re: Yet another attempt at typed JS data

2020-02-12 Thread Andrea Giammarchi
That indeed worked:

```
V8 version 8.2.34
d8> %DebugPrint(Array.from(Array(2), (_, i) => i));
DebugPrint: 0x1c67080c5ddd: [JSArray]
 - map: 0x1c67082817f1  [FastProperties]
 - prototype: 0x1c6708248f7d 
 - elements: 0x1c67080c5ded  [PACKED_SMI_ELEMENTS]
 - length: 2
 - properties: 0x1c67080406e9  {
#length: 0x1c67081c0165  (const accessor descriptor)
 }
 - elements: 0x1c67080c5ded  {
   0: 0
   1: 1
 2-3: 0x1c6708040385 
 }
0x1c67082817f1: [Map]
 - type: JS_ARRAY_TYPE
 - instance size: 16
 - inobject properties: 0
 - elements kind: PACKED_SMI_ELEMENTS
 - unused property fields: 0
 - enum length: invalid
 - back pointer: 0x1c670804030d 
 - prototype_validity cell: 0x1c67081c0451 
 - instance descriptors #1: 0x1c6708249605 
 - transitions #1: 0x1c6708249621 Transition array #1:
 0x1c6708042e91 : (transition to
HOLEY_SMI_ELEMENTS) -> 0x1c6708281869 

 - prototype: 0x1c6708248f7d 
 - constructor: 0x1c6708248e51 
 - dependent code: 0x1c67080401ed 
 - construction counter: 0

[0, 1]
```

> It could maybe be a conceivable argument for introducing
`Array.createAsNonSparse(2)`.

My proposal basically boils down, if we don't like the `TypedArray`
concept, to this:

```js
Array.createAsNonSparse(
  length, // pre-defined length of the Array
  optionalValueOrCallback // values per each entry
);

Array.createAsNonSparse(3, 0); // [0, 0, 0] non sparsed
Array.createAsNonSparse(3, i => i * i); // [0, 1, 4] non sparsed
```

Would this makes more sense? It'd be super handy in many cases, as many
developers don't even know what is a holey/sparsed Array, neither how to
*not* create one.

If the second argument is too ambiguous, I wouldn't mind having it as
function all the time:

```js
Array.createAsNonSparse(3); // [undefined, undefined, undefined] non sparsed
Array.createAsNonSparse(3, () => 0); // [0, 0, 0] non sparsed
Array.createAsNonSparse(3, i => i * i); // [0, 1, 4] non sparsed
```

Thanks.



On Wed, Feb 12, 2020 at 12:51 PM Claude Pache 
wrote:

> At some point in the algorithm of [Array.from], the newly-created array
> will indeed be created as sparse (at steps 9/10), but this is usually not
> observable (that is, unless you are creating an instance of a subclass of
> Array with very unusual behaviour) as far as the spec is concerned
> (optimisation is not part of the spec).
>
> If it is important for you to circumvent the v8 limitation in its
> optimisation process, you should be able to write `Array.from(Array(2), _
> => undefined)`: the array will be created as non-sparse at steps 5.a/b.
>
> In any case, this optimisation detail is by very far not a satisfactory
> argument for introducing the heavy feature you proposed. It could maybe be
> a conceivable argument for introducing `Array.createAsNonSparse(2)`.
>
> [Array.from]: https://tc39.es/ecma262/#sec-array.from
>
> —Claude
>
>
> Le 12 févr. 2020 à 10:23, Andrea Giammarchi 
> a écrit :
>
> Which part of `HOLEY_SMI_ELEMENTS` makes you think so?
>
> V8 version 8.2.34
> d8> %DebugPrint(Array.from({length: 2}, (_, i) => i))
> DebugPrint: 0x5ab080c5ded: [JSArray]
>  - map: 0x05ab08281869  [FastProperties]
>  - prototype: 0x05ab08248f7d 
>  - elements: 0x05ab080c5dfd  [HOLEY_SMI_ELEMENTS]
>  - length: 2
>  - properties: 0x05ab080406e9  {
> #length: 0x05ab081c0165  (const accessor descriptor)
>  }
>  - elements: 0x05ab080c5dfd  {
>0: 0
>1: 1
>  }
> 0x5ab08281869: [Map]
>  - type: JS_ARRAY_TYPE
>  - instance size: 16
>  - inobject properties: 0
>  - elements kind: HOLEY_SMI_ELEMENTS
>  - unused property fields: 0
>  - enum length: invalid
>  - back pointer: 0x05ab082817f1 
>  - prototype_validity cell: 0x05ab081c0451 
>  - instance descriptors #1: 0x05ab08249605 
>  - transitions #1: 0x05ab08249639 Transition array #1:
>  0x05ab08042e91 : (transition to
> PACKED_DOUBLE_ELEMENTS) -> 0x05ab08281891 
>
>  - prototype: 0x05ab08248f7d 
>  - constructor: 0x05ab08248e51 
>  - dependent code: 0x05ab080401ed  (WEAK_FIXED_ARRAY_TYPE)>
>  - construction counter: 0
>
> [0, 1]
>
> On Wed, Feb 12, 2020 at 7:01 AM Jordan Harband  wrote:
>
>> No, `Array.from` never produces a holey array whatsoever; only ever a
>> dense array.
>>
>> On Sun, Feb 9, 2020 at 11:08 PM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a
>>> holey array, so that the `.repeat(...)` idea, if capable of packing
>>> elements in a better way, wouldn't be so terrible, as simplification.
>>>
>>> Although, the intent of this proposal was to also grant "shapes" or
>>> kindness of each entry, same way typed Arrays 

Re: Yet another attempt at typed JS data

2020-02-12 Thread Andrea Giammarchi
Which part of `HOLEY_SMI_ELEMENTS` makes you think so?

V8 version 8.2.34
d8> %DebugPrint(Array.from({length: 2}, (_, i) => i))
DebugPrint: 0x5ab080c5ded: [JSArray]
 - map: 0x05ab08281869  [FastProperties]
 - prototype: 0x05ab08248f7d 
 - elements: 0x05ab080c5dfd  [HOLEY_SMI_ELEMENTS]
 - length: 2
 - properties: 0x05ab080406e9  {
#length: 0x05ab081c0165  (const accessor descriptor)
 }
 - elements: 0x05ab080c5dfd  {
   0: 0
   1: 1
 }
0x5ab08281869: [Map]
 - type: JS_ARRAY_TYPE
 - instance size: 16
 - inobject properties: 0
 - elements kind: HOLEY_SMI_ELEMENTS
 - unused property fields: 0
 - enum length: invalid
 - back pointer: 0x05ab082817f1 
 - prototype_validity cell: 0x05ab081c0451 
 - instance descriptors #1: 0x05ab08249605 
 - transitions #1: 0x05ab08249639 Transition array #1:
 0x05ab08042e91 : (transition to
PACKED_DOUBLE_ELEMENTS) -> 0x05ab08281891 

 - prototype: 0x05ab08248f7d 
 - constructor: 0x05ab08248e51 
 - dependent code: 0x05ab080401ed 
 - construction counter: 0

[0, 1]

On Wed, Feb 12, 2020 at 7:01 AM Jordan Harband  wrote:

> No, `Array.from` never produces a holey array whatsoever; only ever a
> dense array.
>
> On Sun, Feb 9, 2020 at 11:08 PM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a
>> holey array, so that the `.repeat(...)` idea, if capable of packing
>> elements in a better way, wouldn't be so terrible, as simplification.
>>
>> Although, the intent of this proposal was to also grant "shapes" or
>> kindness of each entry, same way typed Arrays do, but maybe that would
>> require some better primitive, as in `const Shape =
>> Object.defineShape(...)` and `Object.createShape(Shape)` or similar.
>>
>> On Sun, Feb 9, 2020 at 10:01 PM Jordan Harband  wrote:
>>
>>> That already exists - `Array.from({ length: 4 }, () => whatever)` - I
>>> assume that the hope is to have an array where it is *impossible* for it to
>>> have the wrong "kind" of data, and a userland factory function wouldn't
>>> provide that.
>>>
>>> On Sun, Feb 9, 2020 at 10:39 AM kai zhu  wrote:
>>>
>>>> > It's a bit of a mess to create an Array that is not holed and gets
>>>> best optimizations [1], and this proposal would like to address that exact
>>>> case.
>>>>
>>>> could the performance issue be resolved more easily with a simple
>>>> static-function `Array.repeat(, )`?
>>>>
>>>> ```js
>>>> let structuredList;
>>>> structuredList = Array.repeat(4, function (ii) {
>>>> return {
>>>> index: 2 * ii + 1,
>>>> tags: []
>>>> });
>>>> /*
>>>> structuredList = [
>>>> { index: 1, tags: [] },
>>>> { index: 3, tags: [] },
>>>> { index: 5, tags: [] },
>>>> { index: 7, tags: [] }
>>>> ];
>>>>  */
>>>> ```
>>>>
>>>> the only time i can practically enforce the shape of a
>>>> "StructuredArray" is during element-insertion,
>>>> and a userland insertion/creation function would be just as effective
>>>> as a StructuredArray constructor.
>>>>
>>>> enforcing shapes during element deletions and updates are going to be
>>>> hard
>>>> and likely just as confusing with StructuredArray as they are with
>>>> regular Array.
>>>>
>>>> also note that most javascript arrays need to be easily JSON-serialized
>>>> for message-passing
>>>> over-the-wire (commonly http) to external systems.
>>>>
>>>> -kai
>>>>
>>>> On Sat, Feb 8, 2020 at 3:46 AM Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> > having to retroactively add checks like...
>>>>>
>>>>> we already have typed arrays in JS so I don't think this would be any
>>>>> different
>>>>>
>>>>> > I _think_ that moderns virtual machines already did these
>>>>> optimisations despite there isn't a TypedArray like that.
>>>>>
>>>>> It's a bit of a mess to create an Array that is not holed and gets
>>>>> best optimizations [1], and this proposal would like to address that exact
>>>>> case.
>>>>>
>>>>> [1] https://v8.dev/blog/elements-kinds
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> ___
>>>>> 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: Yet another attempt at typed JS data

2020-02-11 Thread Andrea Giammarchi
So ...

On Tue, Feb 11, 2020 at 5:44 PM Isiah Meadows 
wrote:

> You have proof of this? That it doesn't produce a dense array in engines?
>

Yes, I have d8 traces, after long discussions in twitter too, that shows
there's no way to have PACKED_SMI_ELEMENTS, but also a bug in Chromium from
2017, but if you need any other proof, I can figure out which other engine
has the same issue, although I am not sure all engines follow same
optimizations with the "packed" vs "holey" v8 concept.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Yet another attempt at typed JS data

2020-02-10 Thread Andrea Giammarchi
> Given your history I know better than to assume what you know…

I've no idea what you are talking about, but this should be no venue for
these kind of answers.

My history in this thread explained the proposal, the intent, and linked
all the facts around it, and before your pointless answer, so please keep
your biases for yourself.

Thank you.


On Mon, Feb 10, 2020 at 10:13 PM Michael Haufe 
wrote:

> Given your history I know better than to assume what you know…
>
>
>
> The definition of sparse in the spec (while not explicitly in its own
> section) is straightforward.
>
>
>
> V8’s inability or unwillingness to perform a safe “upcast” internally to
> an appropriate tag doesn’t seem to provide enough weight to introduce a new
> construct.
>
>
>
>
>
> *From:* Andrea Giammarchi 
> *Sent:* Monday, February 10, 2020 2:26 PM
> *To:* Michael Haufe 
> *Cc:* Bergi ; es-discuss@mozilla.org
> *Subject:* Re: Yet another attempt at typed JS data
>
>
>
> Great, now maybe you also read how it works behind the scene, and debug
> properly to understand that every array is holey, including the latter one,
> to date.
>
>
>
> https://v8.dev/blog/elements-kinds
>
>
>
> Please, let's assume for a second I knew what I was talking about, when
> I've said it's a mess to not have holey arrays, thanks.
>
>
>
> On Mon, Feb 10, 2020 at 9:21 PM Michael Haufe 
> wrote:
>
> Array(3)
> //  [empty × 3]
>
> Array(3).fill()
> // [undefined, undefined, undefined]
>
> Array(3).fill('whatever')
> // ["whatever", "whatever", "whatever"]
>
>
> -Original Message-
> From: es-discuss  On Behalf Of Bergi
> Sent: Monday, February 10, 2020 1:27 PM
> To: es-discuss@mozilla.org
> Subject: Re: Yet another attempt at typed JS data
>
> Hello!
>
> > Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a
> > holey array
>
> Does it? But really, if the performance difference betweeen HOLEY and
> PACKED arrays were large enough to be relevant[1], the engine programmers
> would certainly already have optimised all those trivial cases where an
> array is filled gradually to produce the more efficient representation.
>
> kind regards,
>  Bergi
>
> [1]: it probably isn't:
> https://stackoverflow.com/questions/54481918/#comment95848513_54485509
> ___
> 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: Yet another attempt at typed JS data

2020-02-10 Thread Andrea Giammarchi
Great, now maybe you also read how it works behind the scene, and debug
properly to understand that every array is holey, including the latter one,
to date.

https://v8.dev/blog/elements-kinds

Please, let's assume for a second I knew what I was talking about, when
I've said it's a mess to not have holey arrays, thanks.

On Mon, Feb 10, 2020 at 9:21 PM Michael Haufe 
wrote:

> Array(3)
> //  [empty × 3]
>
> Array(3).fill()
> // [undefined, undefined, undefined]
>
> Array(3).fill('whatever')
> // ["whatever", "whatever", "whatever"]
>
>
> -Original Message-
> From: es-discuss  On Behalf Of Bergi
> Sent: Monday, February 10, 2020 1:27 PM
> To: es-discuss@mozilla.org
> Subject: Re: Yet another attempt at typed JS data
>
> Hello!
>
> > Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a
> > holey array
>
> Does it? But really, if the performance difference betweeen HOLEY and
> PACKED arrays were large enough to be relevant[1], the engine programmers
> would certainly already have optimised all those trivial cases where an
> array is filled gradually to produce the more efficient representation.
>
> kind regards,
>  Bergi
>
> [1]: it probably isn't:
> https://stackoverflow.com/questions/54481918/#comment95848513_54485509
> ___
> 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: Yet another attempt at typed JS data

2020-02-10 Thread Andrea Giammarchi
They couldn't even optimize the most obvious case of them all:
https://bugs.chromium.org/p/v8/issues/detail?id=6892

And "javascript is not the best tool for the job" makes no sense when it's
the most targeted transpiled language, but fair enough.

And yes, I've used SQLite wasm version too ... as a matter of fact, it's
going to be a great lazy-loaded thing for my next project, 'cause it's 1MB
overhead, so not something to really promote in the wild, imho 😅

Regards.

On Mon, Feb 10, 2020 at 8:26 PM Bergi  wrote:

> Hello!
>
> > Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a
> holey
> > array
>
> Does it? But really, if the performance difference betweeen HOLEY and
> PACKED arrays were large enough to be relevant[1], the engine
> programmers would certainly already have optimised all those trivial
> cases where an array is filled gradually to produce the more efficient
> representation.
>
> kind regards,
>  Bergi
>
> [1]: it probably isn't:
> https://stackoverflow.com/questions/54481918/#comment95848513_54485509
> ___
> 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: Yet another attempt at typed JS data

2020-02-10 Thread Andrea Giammarchi
Unfortunately, `Array.from({ length: 4 }, () => whatever)` produces a holey
array, so that the `.repeat(...)` idea, if capable of packing elements in a
better way, wouldn't be so terrible, as simplification.

Although, the intent of this proposal was to also grant "shapes" or
kindness of each entry, same way typed Arrays do, but maybe that would
require some better primitive, as in `const Shape =
Object.defineShape(...)` and `Object.createShape(Shape)` or similar.

On Sun, Feb 9, 2020 at 10:01 PM Jordan Harband  wrote:

> That already exists - `Array.from({ length: 4 }, () => whatever)` - I
> assume that the hope is to have an array where it is *impossible* for it to
> have the wrong "kind" of data, and a userland factory function wouldn't
> provide that.
>
> On Sun, Feb 9, 2020 at 10:39 AM kai zhu  wrote:
>
>> > It's a bit of a mess to create an Array that is not holed and gets best
>> optimizations [1], and this proposal would like to address that exact case.
>>
>> could the performance issue be resolved more easily with a simple
>> static-function `Array.repeat(, )`?
>>
>> ```js
>> let structuredList;
>> structuredList = Array.repeat(4, function (ii) {
>> return {
>> index: 2 * ii + 1,
>> tags: []
>> });
>> /*
>> structuredList = [
>> { index: 1, tags: [] },
>> { index: 3, tags: [] },
>> { index: 5, tags: [] },
>> { index: 7, tags: [] }
>> ];
>>  */
>> ```
>>
>> the only time i can practically enforce the shape of a "StructuredArray"
>> is during element-insertion,
>> and a userland insertion/creation function would be just as effective as
>> a StructuredArray constructor.
>>
>> enforcing shapes during element deletions and updates are going to be hard
>> and likely just as confusing with StructuredArray as they are with
>> regular Array.
>>
>> also note that most javascript arrays need to be easily JSON-serialized
>> for message-passing
>> over-the-wire (commonly http) to external systems.
>>
>> -kai
>>
>> On Sat, Feb 8, 2020 at 3:46 AM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> > having to retroactively add checks like...
>>>
>>> we already have typed arrays in JS so I don't think this would be any
>>> different
>>>
>>> > I _think_ that moderns virtual machines already did these
>>> optimisations despite there isn't a TypedArray like that.
>>>
>>> It's a bit of a mess to create an Array that is not holed and gets best
>>> optimizations [1], and this proposal would like to address that exact case.
>>>
>>> [1] https://v8.dev/blog/elements-kinds
>>>
>>>
>>>
>>>
>>> ___
>>> 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: Yet another attempt at typed JS data

2020-02-08 Thread Andrea Giammarchi
> having to retroactively add checks like...

we already have typed arrays in JS so I don't think this would be any
different

> I _think_ that moderns virtual machines already did these optimisations
despite there isn't a TypedArray like that.

It's a bit of a mess to create an Array that is not holed and gets best
optimizations [1], and this proposal would like to address that exact case.

[1] https://v8.dev/blog/elements-kinds
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Yet another attempt at typed JS data

2020-02-07 Thread Andrea Giammarchi
Any name would do, I'm rather interested in the proposal itself, and its
ergonomics/logic ;-)

On Fri, Feb 7, 2020 at 10:11 PM Scott Rudiger 
wrote:

> `StructuredArray` or `StructArray` for short? Just throwing it out there.
>
> On Fri, Feb 7, 2020, 1:08 PM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> well, this proposal has nothing to do with Typed Arrays, as these are all
>> fixed size indeed ... scratch the TypedArray name, and use ArrayKind
>> instead, any better outcome?
>>
>> On Fri, Feb 7, 2020 at 7:51 PM Jordan Harband  wrote:
>>
>>> the "type" in Typed Arrays refers to the bit size in memory; being able
>>> to pass an arbitrary value seems like it would require implementations to
>>> calculate the precise (not just the maximum) memory size a single item
>>> requires.
>>>
>>> On Fri, Feb 7, 2020 at 6:33 AM Andrea Giammarchi <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> As more and more often devs are shifting into TS, or would like to have
>>>> dynamic typed arrays without a fixed length, and as v8 and likely other
>>>> engines too optimize a lot for same-kind arrays, I wonder what people here
>>>> think about this `TypedArray` rough proposal:
>>>>
>>>> # Signature:
>>>>
>>>> ```js
>>>> new TypedArray(
>>>>   type,   // either a "type" to infer, or a shape, or a Class
>>>>   length  // optional: if defined it's fixed size
>>>> );
>>>> ```
>>>>
>>>>
>>>> ## About the `type`
>>>>
>>>>   * if the inferred type is `object`:
>>>> * if the object is `null`, throw new InvalidType
>>>> * if the object is a literal, or its `__proto__` is either `null`
>>>> or `Object.prototype, enforce own properties and respective types
>>>> * if the object is not literal, fallback to object Class (`/./` is
>>>> `RegExp`, `() => {}` is `Function`, etc)
>>>>   * if the inferred `type` is `function`, fallback to Class
>>>>   * if the inferred `type` is `Class`, ensure each entry is an instance
>>>> of such class, or throw InvalidType
>>>>   * in every other case, make a _typed_ collection of `number`,
>>>> `string`, `boolean`, or `symbol`
>>>>
>>>>
>>>> ## About the `length`
>>>>
>>>>   * if provided, the collection has a fixed, immutable, length, and
>>>> each initial entry a default value
>>>>
>>>>
>>>> # Use Cases:
>>>>
>>>> ```js
>>>> const numbers = new TypedArray(0, 5);
>>>> // creates [0, 0, 0, 0, 0]
>>>> // numbers length is immutable
>>>> // numbers accepts only typeof number
>>>> // out of bound entries throw
>>>>
>>>> let numbers = new TypedArray(0);
>>>> // numbers length is dynamic
>>>> // numbers accepts only typeof number
>>>> // out of bound entries throw
>>>>
>>>> const shapes = new TypedArray({name: '', age: 0}, 3);
>>>> // creates [{name: '', age: 0}, {name: '', age: 0}, {name: '', age: 0}]
>>>> // shapes length is immutable
>>>> // shapes accepts only objects with `name` and `age` and respective
>>>> types
>>>> // out of bound entries throw
>>>>
>>>> let shapes = new TypedArray({lat: 0, long: 0});
>>>> // shapes length is dynamic
>>>> // shapes accepts only objects with `lat` and `long` and respective
>>>> types
>>>> // out of bound entries throw
>>>>
>>>> const classes = new TypedArray(HTMLElement, 2);
>>>> // creates [Object.create(HTMLElement.prototype),
>>>> Object.create(HTMLElement.prototype)]
>>>> // classes length is immutable
>>>> // classes accepts only instances of HTMLElement
>>>> // out of bound entries throw
>>>>
>>>> let classes = new TypedArray(HTMLElement);
>>>> // classes length is dynamic
>>>> // classes accepts only instances of HTMLElement
>>>> // out of bound entries throw
>>>>
>>>> // more options
>>>> let strings = new TypedArray('');
>>>> let booleans = new TypedArray(true);
>>>> let functions = new TypedArray(Function);
>>>> let coords = new TypedArray({lat: 0, long: 0});
>>>> ```
>>>>
>>>> Thanks in advance for eventual thoughts on 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
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Yet another attempt at typed JS data

2020-02-07 Thread Andrea Giammarchi
well, this proposal has nothing to do with Typed Arrays, as these are all
fixed size indeed ... scratch the TypedArray name, and use ArrayKind
instead, any better outcome?

On Fri, Feb 7, 2020 at 7:51 PM Jordan Harband  wrote:

> the "type" in Typed Arrays refers to the bit size in memory; being able to
> pass an arbitrary value seems like it would require implementations to
> calculate the precise (not just the maximum) memory size a single item
> requires.
>
> On Fri, Feb 7, 2020 at 6:33 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> As more and more often devs are shifting into TS, or would like to have
>> dynamic typed arrays without a fixed length, and as v8 and likely other
>> engines too optimize a lot for same-kind arrays, I wonder what people here
>> think about this `TypedArray` rough proposal:
>>
>> # Signature:
>>
>> ```js
>> new TypedArray(
>>   type,   // either a "type" to infer, or a shape, or a Class
>>   length  // optional: if defined it's fixed size
>> );
>> ```
>>
>>
>> ## About the `type`
>>
>>   * if the inferred type is `object`:
>> * if the object is `null`, throw new InvalidType
>> * if the object is a literal, or its `__proto__` is either `null` or
>> `Object.prototype, enforce own properties and respective types
>> * if the object is not literal, fallback to object Class (`/./` is
>> `RegExp`, `() => {}` is `Function`, etc)
>>   * if the inferred `type` is `function`, fallback to Class
>>   * if the inferred `type` is `Class`, ensure each entry is an instance
>> of such class, or throw InvalidType
>>   * in every other case, make a _typed_ collection of `number`, `string`,
>> `boolean`, or `symbol`
>>
>>
>> ## About the `length`
>>
>>   * if provided, the collection has a fixed, immutable, length, and each
>> initial entry a default value
>>
>>
>> # Use Cases:
>>
>> ```js
>> const numbers = new TypedArray(0, 5);
>> // creates [0, 0, 0, 0, 0]
>> // numbers length is immutable
>> // numbers accepts only typeof number
>> // out of bound entries throw
>>
>> let numbers = new TypedArray(0);
>> // numbers length is dynamic
>> // numbers accepts only typeof number
>> // out of bound entries throw
>>
>> const shapes = new TypedArray({name: '', age: 0}, 3);
>> // creates [{name: '', age: 0}, {name: '', age: 0}, {name: '', age: 0}]
>> // shapes length is immutable
>> // shapes accepts only objects with `name` and `age` and respective types
>> // out of bound entries throw
>>
>> let shapes = new TypedArray({lat: 0, long: 0});
>> // shapes length is dynamic
>> // shapes accepts only objects with `lat` and `long` and respective types
>> // out of bound entries throw
>>
>> const classes = new TypedArray(HTMLElement, 2);
>> // creates [Object.create(HTMLElement.prototype),
>> Object.create(HTMLElement.prototype)]
>> // classes length is immutable
>> // classes accepts only instances of HTMLElement
>> // out of bound entries throw
>>
>> let classes = new TypedArray(HTMLElement);
>> // classes length is dynamic
>> // classes accepts only instances of HTMLElement
>> // out of bound entries throw
>>
>> // more options
>> let strings = new TypedArray('');
>> let booleans = new TypedArray(true);
>> let functions = new TypedArray(Function);
>> let coords = new TypedArray({lat: 0, long: 0});
>> ```
>>
>> Thanks in advance for eventual thoughts on 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


Yet another attempt at typed JS data

2020-02-07 Thread Andrea Giammarchi
As more and more often devs are shifting into TS, or would like to have
dynamic typed arrays without a fixed length, and as v8 and likely other
engines too optimize a lot for same-kind arrays, I wonder what people here
think about this `TypedArray` rough proposal:

# Signature:

```js
new TypedArray(
  type,   // either a "type" to infer, or a shape, or a Class
  length  // optional: if defined it's fixed size
);
```


## About the `type`

  * if the inferred type is `object`:
* if the object is `null`, throw new InvalidType
* if the object is a literal, or its `__proto__` is either `null` or
`Object.prototype, enforce own properties and respective types
* if the object is not literal, fallback to object Class (`/./` is
`RegExp`, `() => {}` is `Function`, etc)
  * if the inferred `type` is `function`, fallback to Class
  * if the inferred `type` is `Class`, ensure each entry is an instance of
such class, or throw InvalidType
  * in every other case, make a _typed_ collection of `number`, `string`,
`boolean`, or `symbol`


## About the `length`

  * if provided, the collection has a fixed, immutable, length, and each
initial entry a default value


# Use Cases:

```js
const numbers = new TypedArray(0, 5);
// creates [0, 0, 0, 0, 0]
// numbers length is immutable
// numbers accepts only typeof number
// out of bound entries throw

let numbers = new TypedArray(0);
// numbers length is dynamic
// numbers accepts only typeof number
// out of bound entries throw

const shapes = new TypedArray({name: '', age: 0}, 3);
// creates [{name: '', age: 0}, {name: '', age: 0}, {name: '', age: 0}]
// shapes length is immutable
// shapes accepts only objects with `name` and `age` and respective types
// out of bound entries throw

let shapes = new TypedArray({lat: 0, long: 0});
// shapes length is dynamic
// shapes accepts only objects with `lat` and `long` and respective types
// out of bound entries throw

const classes = new TypedArray(HTMLElement, 2);
// creates [Object.create(HTMLElement.prototype),
Object.create(HTMLElement.prototype)]
// classes length is immutable
// classes accepts only instances of HTMLElement
// out of bound entries throw

let classes = new TypedArray(HTMLElement);
// classes length is dynamic
// classes accepts only instances of HTMLElement
// out of bound entries throw

// more options
let strings = new TypedArray('');
let booleans = new TypedArray(true);
let functions = new TypedArray(Function);
let coords = new TypedArray({lat: 0, long: 0});
```

Thanks in advance for eventual thoughts on this 👋
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-15 Thread Andrea Giammarchi
> You still seem to be misunderstanding what the execution order difference
is about.

If to stop this thread you need me to say I am confused about anything then
fine, "I am confused", but if you keep changing my examples to make your
point then this conversation goes nowhere, so I am officially out of this
thread.

Best Regards.

On Mon, Oct 14, 2019 at 10:41 PM Tab Atkins Jr. 
wrote:

> On Sat, Oct 12, 2019 at 7:19 AM Andrea Giammarchi
>  wrote:
> > in order to work, `await` must be executed in an async scope/context
> (either top level or within a closure).
> >
> > In such case, either somebody is awaiting the result of that `async`
> execution, or the order doesn't matter.
>
> That's definitely not true. I gave you an explicit example where the
> order differs. That example code is realistic if you're using the
> async call for side-effects only (and thus don't care about the
> returned promise), or if you're storing the returned promise in a
> variable so you can pass it to one of the promise combinators later.
> In either of these cases the order of execution between the sync and
> async code can definitely matter.
>
> > The following two examples produce indeed the very same result:
> >
> > ```js
> > (async () => { return 1; })().then(console.log);
> > console.log(2);
> >
> > (async () => { return await 1; })().then(console.log);
> > console.log(2);
> > ```
>
> In both of these cases, you're doing no additional work after the
> "maybe async" point. That is the exact part that moves in execution
> order between the two cases, so obviously you won't see any
> difference.  Here's a slightly altered version that shows off the
> difference:
>
> ```js
> (async () => { 1; console.log("async"); return 3; })().then(console.log);
> console.log(2);
>
> (async () => { await 1; console.log("async"); return 3;
> })().then(console.log);
> console.log(2);
> ```
>
> In the first you'll log "async", "2", "3". In the second you'll log
> "2", "async", "3".
>
> > As summary: the proposal was to help engines be faster when it's
> possible, but devs are confused by the syntax, and maybeat the end there
> wouldn't be as many benefits compared to the apparent confusion this
> proposal would add.
>
> You still seem to be misunderstanding what the execution order
> difference is about. Nobody's confused about the syntax; it's clear
> enough. It just does bad, confusing things as you've presented it.
>
> As I said in earlier message, there *is* a way to eliminate the
> execution-order difference (making it so the only difference would be
> the number of microtasks when your function awaits *multiple* sync
> values), which I thought you'd come up with at some point, but I'm
> pretty sure it was just me misunderstanding what you'd said.
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-12 Thread Andrea Giammarchi
in order to work, `await` must be executed in an async scope/context
(either top level or within a closure).

In such case, either somebody is awaiting the result of that `async`
execution, or the order doesn't matter.

The following two examples produce indeed the very same result:

```js
(async () => { return 1; })().then(console.log);
console.log(2);

(async () => { return await 1; })().then(console.log);
console.log(2);
```

Except the second one will be scheduled a micro task too far.

Since nobody counts the amount of microtasks per async function execution,
the result is practically the same, except the second example is always
slower.

Putting all together:

```js
(async () => { return await 'third'; })().then(console.log);
(async () => { return 'second'; })().then(console.log);
console.log('first');
```

If you `await` the return of an async function, you are consuming that
microtask regardless, which is what `await?` here would like to avoid: do
not create a micro task when it's not necessary.

There's no footgun as the `await?` is an explicit intent from the
developer, so if the developer knows what s/he's doing, can use `await?`,
otherwise if the order of the microtask matters at all, can always just use
`await`.

As summary: the proposal was to help engines be faster when it's possible,
but devs are confused by the syntax, and maybeat the end there wouldn't be
as many benefits compared to the apparent confusion this proposal would add.

I hope I've explained properly what was this about.

Regards


On Fri, Oct 11, 2019 at 10:43 PM Tab Atkins Jr. 
wrote:

> On Fri, Oct 11, 2019 at 1:15 AM Andrea Giammarchi
>  wrote:
> > Again, the `await?` is sugar for the following:
> >
> > ```js
> > const value = await? callback();
> >
> > // as sugar for
> > let value = callback();
> > if ('then' in value)
> >   value = await value;
> > ```
>
> Okay, so that has the "you can't predict execution order any more"
> problem. But that's not consistent with what you said in "otherwise
> schedule a single microtask if none has been scheduled already, or
> queue this result to the previous scheduled one", which implies a
> different desugaring:
>
> ```js
> let value = callback();
> if('then' in value || thisFunctionHasntAwaitedYet)
>   value = await value;
> ```
>
> *This* desugaring has a consistent execution order, and still meets
> your goal of "don't add a bunch of microtask checkpoints for
> synchronous values".
>
> Put another way, this `await?` is equivalent to `await` *if* you're
> still in the "synchronously execute until you hit the first await"
> phase of executing an async function; but it's equivalent to your
> simpler desugaring ("await only if this is a thenable") after that.
>
> > but since I've stated already I have no interest anymore in this
> proposal, we can also stop explaining to each others things we know already.
>
> I'm fine if you want to drop it, but we're not explaining things we
> already know to each other. At least one of us is confused about
> what's being proposed. And the altered desugaring I give up above at
> least has a chance of happening; the only issue might be the
> observability of how many microtasks get scheduled. If that's not a
> problem, it might be possible to suggest this as an actual change to
> how `await` works.
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-11 Thread Andrea Giammarchi
Again, the `await?` is sugar for the following:

```js
const value = await? callback();

// as sugar for
let value = callback();
if ('then' in value)
  value = await value;
```

but since I've stated already I have no interest anymore in this proposal,
we can also stop explaining to each others things we know already.

Best Regards

On Fri, Oct 11, 2019 at 1:32 AM Tab Atkins Jr.  wrote:

> On Wed, Oct 9, 2019 at 11:17 PM Andrea Giammarchi
>  wrote:
> > > What's the order of the logs?
> >
> > Exactly the same, as the `await?` is inevitably inside an `async`
> function which would grant a single microtask instead of N.
>
> I think you're misreading my example?  Check this out:
> http://software.hixie.ch/utilities/js/live-dom-viewer/saved/7271
>
> ```html
> 
> 
> function one() {
>   oneAsync();
>   w("one A");
> }
> async function oneAsync() {
>   await Promise.resolve();
>   w("one B");
> }
>
> function two() {
>   twoAsync();
>   w("two A");
> }
>
> async function twoAsync() {
>   // await? true;
>   w("two B");
> }
>
> one();
> two();
> 
> ```
>
> This script logs:
>
> ```
> log: one A
> log: two B
> log: two A
> log: one B
> ```
>
> A and B are logged in different order depends on whether there's an
> `await` creating a microtask checkpoint or not. `await? true` won't
> create a microtask checkpoint, so you'll get the two() behavior,
> printing B then A. `await? Promise.resolve(true)` will create one, so
> you'll get the one() behavior, printing A then B.
>
> > If `maybeAsync` returns twice non promises results, there is only one
> microtask within the async `tasks` function, that would linearly collect
> all non promises, so that above example could have 1, 2, max 4 microtasks,
> instead of always 4
> > .
> > To explain `await?` in steps:
> >
> >   * is the awaited value a promise? schedule microtask
> >   * otherwise schedule a single microtask if none has been scheduled
> already, or queue this result to the previous scheduled one
> >
> > This would grant same linear order and save time.
>
> Ah, your earlier posts didn't say that `await? nonPromise` *would*
> schedule a microtask in some cases! That does change things.  Hm, I
> wonder if this is observably different from the current behavior?
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-09 Thread Andrea Giammarchi
> What's the order of the logs?

Exactly the same, as the `await?` is inevitably inside an `async` function
which would grant a single microtask instead of N.

Example:

```js
async function tasks() {
  await? maybeAsync();
  await? maybeAsync();
  await? maybeAsync();
}

tasks();
```

If `maybeAsync` returns twice non promises results, there is only one
microtask within the async `tasks` function, that would linearly collect
all non promises, so that above example could have 1, 2, max 4 microtasks,
instead of always 4
.
To explain `await?` in steps:

  * is the awaited value a promise? schedule microtask
  * otherwise schedule a single microtask if none has been scheduled
already, or queue this result to the previous scheduled one

This would grant same linear order and save time.

However, like others said already in the twitter thread, we all wish
`await` was already working like that by default, while it seems to
unconditionally create micro tasks even when it's not strictly necessary.




On Wed, Oct 9, 2019 at 11:47 PM Tab Atkins Jr.  wrote:

> On Wed, Oct 9, 2019 at 12:08 AM Andrea Giammarchi
>  wrote:
> > I don't know why this went in a completely unrelated direction so ...
> I'll try to explain again what is `await?` about.
>
> Nah, we got it. Our complaint was still about the semantics.
>
> > ```js
> > const value = await? callback();
> >
> > // as sugar for
> > let value = callback();
> > if ('then' in value)
> >   value = await value;
> > ```
> >
> > The order is guaranteed and linear in every case, so that nothing
> actually change logically speaking, and the hint would be about
> performance, 'cause engines don't apparently optimize non-promise based
> cases.
>
> Expand that code so there's a caller:
>
> ```js
> function one() {
>   two();
>   console.log("one");
> }
> async function two() {
>   await? maybeAsync();
>   console.log("two");
> }
> ```
>
> What's the order of the logs?
>
> If maybeAsync() is synchronous, then one() calls two(), two() calls
> maybeAsync() which returns immediately, and it continues to log "two"
> before ending and returning execution to one(), which then logs "one"
> and ends.
>
> If maybeAsync() returns a promise, then one() calls two(), two calls
> maybeAsync() then freezes while it waits for the promise to resolve,
> returning execution to one(). Since one() isn't awaiting the promise
> returned by two(), it just immediately continues and logs "one" then
> ends. At some point later in execution, the maybeAsync() promise
> resolves, two() unfreezes, then it logs "two".
>
> So no, the order is not guaranteed. It's unpredictable and depends on
> whether the function being await?'d returns a promise or not. If you
> don't know what maybeAsync() returns, you won't be able to predict
> your own execution flow, which is dangerous and a very likely source
> of bugs.
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Conditional await, anyone?

2019-10-09 Thread Andrea Giammarchi
I don't know why this went in a completely unrelated direction so ... I'll
try to explain again what is `await?` about.

My first two examples show a relevant performance difference between the
async code and the sync one.

The async code though, has zero reasons to be async and so much slower.

```js
(async () => {
  console.time('await');
  const result = await (async () => [await 1, await 2, await 3])();
  console.timeEnd('await');
  return result;
})();
```

Why would `await 1` ever need to create a micro task, if already executed
into a scheduled one via async?

Or in general, why any callback that would early return a value that is not
a promise should create a micro task?

So the proposal was implemented in an attempt to de-sugar `await?` into the
steps proposed by the dev I've interacted with:

```js
const value = await? callback();

// as sugar for
let value = callback();
if ('then' in value)
  value = await value;
```

The order is guaranteed and linear in every case, so that nothing actually
change logically speaking, and the hint would be about performance, 'cause
engines don't apparently optimize non-promise based cases.

However, since the initial intent/proposal about performance got translated
into everything else, I've instantly lost interest myself as it's evident
an `await?` would causes more confusion than it solves.

I am also not answering other points as not relevant for this idea/proposal.

Thanks regardless for sharing your thoughts, it helped me see it would
confuse developers.

Best Regards





On Tue, Oct 8, 2019 at 11:58 PM Dan Peddle  wrote:

> Have to agree, mixing sync and async code like this looks like a disaster
> waiting to happen. Knowing which order your code will be executed in might
> seem not so important for controlled environments where micro optimisations
> are attractive, but thinking about trying to track down a bug through this
> would drive me nuts.
>
> Imagine you have a cached value which can be retrieved synchronously -
> other code which runs in order, and perhaps not directly part of this
> chain, would be fine. When it’s not there, zalgo would indeed be released.
> The solution to this is to use promises (as I’m sure you know) so you have
> a consistent way of saying when something is ready... otherwise it’s
> thenable sniffing all the way through the codebase.
>
> Async infers some kind of IO or deferred process, scheduling. If there’s a
> dependency, then we need to express that. That it may be in some cases
> available synchronously seems like something to be extremely wary of.
>
> > On 8. Oct 2019, at 22:25, Tab Atkins Jr.  wrote:
> >
> > I'm not sure I understand the intended use-case here.  If the author
> > knows the function they're calling is async, they can use `await`
> > normally. If they know it's not async, they can avoid `await`
> > altogether. If they have no idea whether it's async or not, that means
> > they just don't understand what the function is returning, which
> > sounds like a really bad thing that they should fix?  And in that
> > case, as Gus says, `await?`'s semantics would do some confusing things
> > to execution order, making the line after the `await?` either run
> > *before* or *after* the calling code, depending on whether the await'd
> > value was a promise or not.
> >
> > ~TJ
> > ___
> > 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


Conditional await, anyone?

2019-10-08 Thread Andrea Giammarchi
When developers use `async` functions, they'll likely also await
unconditionally any callback, even if such callback could return a non
promise value, for whatever reason.

Engines are great at optimizing stuff, but as of today, if we measure the
performance difference between this code:

```js
(async () => {
  console.time('await');
  const result = await (async () => [await 1, await 2, await 3])();
  console.timeEnd('await');
  return result;
})();
```

and the following one:

```js
(/* sync */ () => {
  console.time('sync');
  const result = (() => [1, 2, 3])();
  console.timeEnd('sync');
  return result;
})();
```

we'll notice the latter is about 10 to 100 times faster than the
asynchronous one.

Sure thing, engines might infer returned values in some hot code and skip
the microtask dance once it's sure some callback might return values that
are not promises, but what if developers could give hints about this
possibility?

In a twitter exchange, one dev mentioned the following:

> I often write:
> let value = mightBePromise()
> if (value && value.then)
>   value = await value
> in hot code in my async functions, for precisely this reason (I too have
measured the large perf difference).

so ... how about accepting a question mark after `await` so that it's clear
the developer knows the function might return non Promise based results,
hence the code could be faster?

```js
const value = await? callback();
```

Above code is basically what's this thread/proposal about, adding a
conditional `await` syntax, so that if the returned value is not thenable,
there's no reason to waste a microtask on it.

What are your thoughts?
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Optional chaining syntax but with the "mice" operator ?

2019-09-09 Thread Andrea Giammarchi
Yes, we can all use N variables in the middle of a chain, but
`any.thing().that.queries().rows` is a more common/natural pattern.

Like in everything in JS, developers need to know what they are doing.
Every operator can create bugs (i.e. NaN results or bad string
concatenations instead of sums) so I'm not sold on developers being
confused: they either understand the code they are writing, or they'll have
code reviews from their peers that hopeful understand the code.

If nobody understands the code, then the code should be changed (as in:
nobody needs to use an operator they don't get).

As summary, I see more advantages than disadvantages, but I've created a
module to solve the same issue to let developers play with it and see if
this might be an interesting extra.

I am not planning to keep stating I don't find it confusing though, and if
everyone else feels like it's confusing, I can live with it and move on
without the mouse trap.

Regards


On Mon, Sep 9, 2019 at 12:02 PM Naveen Chawla  wrote:

> I wasn't comparing it to your `??` variant of the same cases, which has
> the same issues - but only because that is a curious way of using `??` in
> the first place. Ordinarily `??` would be used to resolve to a value *of
> the same type* to allow clear unambiguous data flow through the variables.
>
> Rather, I'm comparing it to
>
> const
> resultsContainer = db.get(SQL),
> firstResultIfExists = rows?.[0]
> ;
>
> This allows re-use of the "resultsContainer" (if desired) without creating
> ambiguity about each variable's meaning. Otherwise if shoehorned into a
> single variable and a developer accidentally makes a wrong presumption
> about the "type" without performing an explicit "type check" (of some kind)
> on the resulting variable, the function would just crash. I know JavaScript
> already allows this via ?? as it's a dynamic language, but the  pretty much encourages it.
>
> The "destructuring" example produces a buggy "rowsCount". It can only ever
> be 0. However, another developer may be tempted to say `else if(rowsCount >
> 1)` not realizing that it's undefined if there are actually any rows. This
> is what I mean by confusing & bug prone results of the pattern.
>
>
> On Mon, 9 Sep 2019 at 10:18, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> I guess we have a different opinion about what's confusing and what's
>> not. To me having a `??` with potential side-effects is more bug prone than
>> the proposed mouse trap, as it's subtle, yet "promoted" by the `?.` + `??`
>> pattern.
>>
>> On Mon, Sep 9, 2019 at 11:16 AM Naveen Chawla 
>> wrote:
>>
>>> "resultsContainerOrSingleResult" appears to be the end variable. I just
>>> find this "shoehorning" to be a sacrifice in code clarity and
>>> manageability. "rowCount" would be undefined if greater than 0 in the 2nd
>>> example, it seems. Surely that is a confusing behaviour, if not bug prone
>>>
>>> On Mon, 9 Sep 2019, 09:17 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> so *maybe* we'll come back...
>>>>
>>>> On Mon, Sep 9, 2019 at 10:04 AM Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> `require("module")>>>> initially explained.
>>>>>
>>>>> `db.get(SQL)>>>> know that won't fail but might not return the desired result, so that you
>>>>> end up holding the top most object with all the informations, instead of
>>>>> simply ending up with undefined. This works well with destructuring too.
>>>>>
>>>>> ```js
>>>>> const {rowsCount, id, name, email} = db.get(SQL)>>>> if (rowCounts === 0)
>>>>>   askUserToRegister();
>>>>> else
>>>>>   showUserDetails();
>>>>> ```
>>>>>
>>>>> As mentioned, there is a module that let you explicitly use this
>>>>> operator through a callback that tries to be as safe as it can (void after
>>>>> first `.trap` access + self clean on next microtask), so manye we'll come
>>>>> back to this discussion once we all understand the use case and why it's
>>>>> actually very useful in some circumstance.
>>>>>
>>>>> Regards
>>>>>
>>>>>
>>>>>
>>>>> On Sat, Sep 7, 2019 at 1:23 PM Naveen Chawla 
>>>>> 

Re: Optional chaining syntax but with the "mice" operator ?

2019-09-09 Thread Andrea Giammarchi
I guess we have a different opinion about what's confusing and what's not.
To me having a `??` with potential side-effects is more bug prone than the
proposed mouse trap, as it's subtle, yet "promoted" by the `?.` + `??`
pattern.

On Mon, Sep 9, 2019 at 11:16 AM Naveen Chawla  wrote:

> "resultsContainerOrSingleResult" appears to be the end variable. I just
> find this "shoehorning" to be a sacrifice in code clarity and
> manageability. "rowCount" would be undefined if greater than 0 in the 2nd
> example, it seems. Surely that is a confusing behaviour, if not bug prone
>
> On Mon, 9 Sep 2019, 09:17 Andrea Giammarchi, 
> wrote:
>
>> so *maybe* we'll come back...
>>
>> On Mon, Sep 9, 2019 at 10:04 AM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> `require("module")>> initially explained.
>>>
>>> `db.get(SQL)>> that won't fail but might not return the desired result, so that you end up
>>> holding the top most object with all the informations, instead of simply
>>> ending up with undefined. This works well with destructuring too.
>>>
>>> ```js
>>> const {rowsCount, id, name, email} = db.get(SQL)>> if (rowCounts === 0)
>>>   askUserToRegister();
>>> else
>>>   showUserDetails();
>>> ```
>>>
>>> As mentioned, there is a module that let you explicitly use this
>>> operator through a callback that tries to be as safe as it can (void after
>>> first `.trap` access + self clean on next microtask), so manye we'll come
>>> back to this discussion once we all understand the use case and why it's
>>> actually very useful in some circumstance.
>>>
>>> Regards
>>>
>>>
>>>
>>> On Sat, Sep 7, 2019 at 1:23 PM Naveen Chawla 
>>> wrote:
>>>
>>>> There has to be a better pattern than returning the "foo()" if the baz
>>>> property doesn't exist.
>>>>
>>>> I'm curious what you would want to do with the resulting "foo()"
>>>> anyway. I can imagine a flow where I want "bar", and it doesn't exist it
>>>> doesn't. I cannot imagine wanting the "foo()" in place of it. There is type
>>>> unpredictability in the result, so subsequent operations would normally
>>>> expected to be impossible without type-branching. Hence my question to you
>>>> about what you would typically want to do with the "foo()" if that was the
>>>> returned result.
>>>>
>>>> On Sat, 7 Sep 2019 at 12:08, Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> Interesting I forgot about that, but it wouldn't cover the "trap here"
>>>>> use case.
>>>>>
>>>>> foo().bar ?! what => what : what;
>>>>>
>>>>> I'd like to forward foo() here
>>>>>
>>>>> On Sat, Sep 7, 2019, 11:45 Michael Luder-Rosefield <
>>>>> rosyatran...@gmail.com> wrote:
>>>>>
>>>>>> This is getting very reminiscent of my 'forwarding ternary' operator
>>>>>> (or whatever I called it) I suggested a couple of years ago. I believe 
>>>>>> you
>>>>>> were involved in the discussion, Andrea...!
>>>>>>
>>>>>> ```
>>>>>> const val = foo() ?!
>>>>>>   (x) => x.bar.baz :
>>>>>>   someFallbackValue;
>>>>>> ```
>>>>>>
>>>>>> On Sat, 7 Sep 2019, 10:17 Andrea Giammarchi, <
>>>>>> andrea.giammar...@gmail.com> wrote:
>>>>>>
>>>>>>> To better answer, let's start dropping any direct access and put a
>>>>>>> payload in the mix.
>>>>>>>
>>>>>>> As example, in the `foo()?.bar.baz` case, you might end up having
>>>>>>> `null` or `undefined`, as result, because `foo().bar` existed, but
>>>>>>> `bar.baz` didn't.
>>>>>>>
>>>>>>> In the `foo()?.bar?.baz` case, you might end up having `foo().bar`,
>>>>>>> because `bar.baz` didn't exist.
>>>>>>>
>>>>>>> But what if you are not interested in the whole chain, but only in a
>>>>>>> main specific point in such chain

Re: Optional chaining syntax but with the "mice" operator ?

2019-09-09 Thread Andrea Giammarchi
so *maybe* we'll come back...

On Mon, Sep 9, 2019 at 10:04 AM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> `require("module") initially explained.
>
> `db.get(SQL) that won't fail but might not return the desired result, so that you end up
> holding the top most object with all the informations, instead of simply
> ending up with undefined. This works well with destructuring too.
>
> ```js
> const {rowsCount, id, name, email} = db.get(SQL) if (rowCounts === 0)
>   askUserToRegister();
> else
>   showUserDetails();
> ```
>
> As mentioned, there is a module that let you explicitly use this operator
> through a callback that tries to be as safe as it can (void after first
> `.trap` access + self clean on next microtask), so manye we'll come back to
> this discussion once we all understand the use case and why it's actually
> very useful in some circumstance.
>
> Regards
>
>
>
> On Sat, Sep 7, 2019 at 1:23 PM Naveen Chawla 
> wrote:
>
>> There has to be a better pattern than returning the "foo()" if the baz
>> property doesn't exist.
>>
>> I'm curious what you would want to do with the resulting "foo()" anyway.
>> I can imagine a flow where I want "bar", and it doesn't exist it doesn't. I
>> cannot imagine wanting the "foo()" in place of it. There is type
>> unpredictability in the result, so subsequent operations would normally
>> expected to be impossible without type-branching. Hence my question to you
>> about what you would typically want to do with the "foo()" if that was the
>> returned result.
>>
>> On Sat, 7 Sep 2019 at 12:08, Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> Interesting I forgot about that, but it wouldn't cover the "trap here"
>>> use case.
>>>
>>> foo().bar ?! what => what : what;
>>>
>>> I'd like to forward foo() here
>>>
>>> On Sat, Sep 7, 2019, 11:45 Michael Luder-Rosefield <
>>> rosyatran...@gmail.com> wrote:
>>>
>>>> This is getting very reminiscent of my 'forwarding ternary' operator
>>>> (or whatever I called it) I suggested a couple of years ago. I believe you
>>>> were involved in the discussion, Andrea...!
>>>>
>>>> ```
>>>> const val = foo() ?!
>>>>   (x) => x.bar.baz :
>>>>   someFallbackValue;
>>>> ```
>>>>
>>>> On Sat, 7 Sep 2019, 10:17 Andrea Giammarchi, <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> To better answer, let's start dropping any direct access and put a
>>>>> payload in the mix.
>>>>>
>>>>> As example, in the `foo()?.bar.baz` case, you might end up having
>>>>> `null` or `undefined`, as result, because `foo().bar` existed, but
>>>>> `bar.baz` didn't.
>>>>>
>>>>> In the `foo()?.bar?.baz` case, you might end up having `foo().bar`,
>>>>> because `bar.baz` didn't exist.
>>>>>
>>>>> But what if you are not interested in the whole chain, but only in a
>>>>> main specific point in such chain? In that case you would have
>>>>> `foo()?.bar.baz ?? foo()`, but you wouldn't know how to obtain that via
>>>>> `foo()?.bar?.baz ?? foo()`, because the latest one might result into
>>>>> `foo().bar`.
>>>>>
>>>>> Moreover, in both cases you'll end up multiplying the payload at least
>>>>> * 2, while the mouse trap will work like this:
>>>>>
>>>>> ```js
>>>>> foo()>>>> ```
>>>>>
>>>>> if either `foo().bar` or `bar.baz` don't exist, the returned result is
>>>>> `foo()`, and it's computed once. You don't care about `foo().bar` if
>>>>> `bar.baz` is not there, 'cause you want to retrieve `foo()` whenever you
>>>>> have a failure down the chain.
>>>>>
>>>>> Specially with DB operations, this is a very common case (abstraction
>>>>> layers all have somehow different nested objects with various info) and 
>>>>> the
>>>>> specific info you want to know is usually attached at the top level bject,
>>>>> while crawling its sub properties either leads to the expected result or
>>>>> you're left clueless about the result, 'cause all info

Re: Optional chaining syntax but with the "mice" operator ?

2019-09-09 Thread Andrea Giammarchi
`require("module") wrote:

> There has to be a better pattern than returning the "foo()" if the baz
> property doesn't exist.
>
> I'm curious what you would want to do with the resulting "foo()" anyway. I
> can imagine a flow where I want "bar", and it doesn't exist it doesn't. I
> cannot imagine wanting the "foo()" in place of it. There is type
> unpredictability in the result, so subsequent operations would normally
> expected to be impossible without type-branching. Hence my question to you
> about what you would typically want to do with the "foo()" if that was the
> returned result.
>
> On Sat, 7 Sep 2019 at 12:08, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> Interesting I forgot about that, but it wouldn't cover the "trap here"
>> use case.
>>
>> foo().bar ?! what => what : what;
>>
>> I'd like to forward foo() here
>>
>> On Sat, Sep 7, 2019, 11:45 Michael Luder-Rosefield <
>> rosyatran...@gmail.com> wrote:
>>
>>> This is getting very reminiscent of my 'forwarding ternary' operator (or
>>> whatever I called it) I suggested a couple of years ago. I believe you were
>>> involved in the discussion, Andrea...!
>>>
>>> ```
>>> const val = foo() ?!
>>>   (x) => x.bar.baz :
>>>   someFallbackValue;
>>> ```
>>>
>>> On Sat, 7 Sep 2019, 10:17 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> To better answer, let's start dropping any direct access and put a
>>>> payload in the mix.
>>>>
>>>> As example, in the `foo()?.bar.baz` case, you might end up having
>>>> `null` or `undefined`, as result, because `foo().bar` existed, but
>>>> `bar.baz` didn't.
>>>>
>>>> In the `foo()?.bar?.baz` case, you might end up having `foo().bar`,
>>>> because `bar.baz` didn't exist.
>>>>
>>>> But what if you are not interested in the whole chain, but only in a
>>>> main specific point in such chain? In that case you would have
>>>> `foo()?.bar.baz ?? foo()`, but you wouldn't know how to obtain that via
>>>> `foo()?.bar?.baz ?? foo()`, because the latest one might result into
>>>> `foo().bar`.
>>>>
>>>> Moreover, in both cases you'll end up multiplying the payload at least
>>>> * 2, while the mouse trap will work like this:
>>>>
>>>> ```js
>>>> foo()>>> ```
>>>>
>>>> if either `foo().bar` or `bar.baz` don't exist, the returned result is
>>>> `foo()`, and it's computed once. You don't care about `foo().bar` if
>>>> `bar.baz` is not there, 'cause you want to retrieve `foo()` whenever you
>>>> have a failure down the chain.
>>>>
>>>> Specially with DB operations, this is a very common case (abstraction
>>>> layers all have somehow different nested objects with various info) and the
>>>> specific info you want to know is usually attached at the top level bject,
>>>> while crawling its sub properties either leads to the expected result or
>>>> you're left clueless about the result, 'cause all info got lost in the
>>>> chain.
>>>>
>>>> The `foo()>>> `foo().bar` existed, there's no way to expect `foo()` as result, and if
>>>> it's `bar` that you're after you can write instead `foo()?.bar>>> that if `baz` is not there, `bar` it is.
>>>>
>>>> This short-circuit the need for `??` in most cases, 'cause you already
>>>> point at the desired result in the chain in case the result would be `null`
>>>> or `undefined`.
>>>>
>>>> However, `??` itself doesn't provide any ability to reach any point in
>>>> the previous chain that failed, so that once again, you find yourself
>>>> crawling such chain as fallback, resulting potentially in multiple chains
>>>> and repeated payloads.
>>>>
>>>> ```js
>>>> // nested chains
>>>> foo()?.bar.baz?.biz ?? foo()?.bar.baz ?? foo()?.bar;
>>>>
>>>> // mouse trap
>>>> foo()?.bar>>> ```
>>>>
>>>> Above example would prefer `foo().bar` if it exists, and if either
>>>> `bar.baz` or `bar.baz.biz` returned `null` or `undefined`.
>>>>
>>>> I hope this

Re: Optional chaining syntax but with the "mice" operator ?

2019-09-07 Thread Andrea Giammarchi
Interesting I forgot about that, but it wouldn't cover the "trap here" use
case.

foo().bar ?! what => what : what;

I'd like to forward foo() here

On Sat, Sep 7, 2019, 11:45 Michael Luder-Rosefield 
wrote:

> This is getting very reminiscent of my 'forwarding ternary' operator (or
> whatever I called it) I suggested a couple of years ago. I believe you were
> involved in the discussion, Andrea...!
>
> ```
> const val = foo() ?!
>   (x) => x.bar.baz :
>   someFallbackValue;
> ```
>
> On Sat, 7 Sep 2019, 10:17 Andrea Giammarchi, 
> wrote:
>
>> To better answer, let's start dropping any direct access and put a
>> payload in the mix.
>>
>> As example, in the `foo()?.bar.baz` case, you might end up having `null`
>> or `undefined`, as result, because `foo().bar` existed, but `bar.baz`
>> didn't.
>>
>> In the `foo()?.bar?.baz` case, you might end up having `foo().bar`,
>> because `bar.baz` didn't exist.
>>
>> But what if you are not interested in the whole chain, but only in a main
>> specific point in such chain? In that case you would have `foo()?.bar.baz
>> ?? foo()`, but you wouldn't know how to obtain that via `foo()?.bar?.baz ??
>> foo()`, because the latest one might result into `foo().bar`.
>>
>> Moreover, in both cases you'll end up multiplying the payload at least *
>> 2, while the mouse trap will work like this:
>>
>> ```js
>> foo()> ```
>>
>> if either `foo().bar` or `bar.baz` don't exist, the returned result is
>> `foo()`, and it's computed once. You don't care about `foo().bar` if
>> `bar.baz` is not there, 'cause you want to retrieve `foo()` whenever you
>> have a failure down the chain.
>>
>> Specially with DB operations, this is a very common case (abstraction
>> layers all have somehow different nested objects with various info) and the
>> specific info you want to know is usually attached at the top level bject,
>> while crawling its sub properties either leads to the expected result or
>> you're left clueless about the result, 'cause all info got lost in the
>> chain.
>>
>> The `foo()> `foo().bar` existed, there's no way to expect `foo()` as result, and if
>> it's `bar` that you're after you can write instead `foo()?.bar> that if `baz` is not there, `bar` it is.
>>
>> This short-circuit the need for `??` in most cases, 'cause you already
>> point at the desired result in the chain in case the result would be `null`
>> or `undefined`.
>>
>> However, `??` itself doesn't provide any ability to reach any point in
>> the previous chain that failed, so that once again, you find yourself
>> crawling such chain as fallback, resulting potentially in multiple chains
>> and repeated payloads.
>>
>> ```js
>> // nested chains
>> foo()?.bar.baz?.biz ?? foo()?.bar.baz ?? foo()?.bar;
>>
>> // mouse trap
>> foo()?.bar> ```
>>
>> Above example would prefer `foo().bar` if it exists, and if either
>> `bar.baz` or `bar.baz.biz` returned `null` or `undefined`.
>>
>> I hope this clarifies further the intent, or the simplification, that
>> such operator offers: it's a complementary hint for any optional chain, it
>> doesn't have to be used, but when it does, it's visually semantic in its
>> intent (at least to my eyes).
>>
>> Regards
>>
>>
>>
>>
>> On Fri, Sep 6, 2019 at 11:20 PM Tab Atkins Jr. 
>> wrote:
>>
>>> On Fri, Sep 6, 2019 at 8:04 AM Andrea Giammarchi
>>>  wrote:
>>> > Indeed I'm not super convinced myself about the "branching issue"
>>> 'cause `const result = this?.is?.branching?.already` and all I am proposing
>>> is to hint the syntax where to stop in case something else fails down the
>>> line, as in `const result = this.?.is>> other part is not reached, there is a certain point to keep going (which
>>> is, example, checking that `result !== this`)
>>>
>>> Important distinction there is that ?. only "branches" between the
>>> intended type and undefined, not between two arbitrary types. The
>>> cognitive load between those two is significantly different.
>>>
>>> In particular, you can't *do* anything with undefined, so
>>> `foo?.bar.baz` has pretty unambiguous semantics - you don't think you
>>> might be accessing the .baz property of undefined, because that
>>> clearly doesn't exist.
>>>
>>> That's not the case with mouse, where it's not clear, at least to me,
>>> whether `foo>> `foo.bar.baz ? foo.bar.baz : foo` or even `foo.bar ? foo.bar.baz :
>>> foo`. All three seem at least somewhat reasonable, and definitely
>>> *believable* as an interpretation!
>>>
>>> ~TJ
>>>
>> ___
>> 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: Optional chaining syntax but with the "mice" operator ?

2019-09-07 Thread Andrea Giammarchi
To better answer, let's start dropping any direct access and put a payload
in the mix.

As example, in the `foo()?.bar.baz` case, you might end up having `null` or
`undefined`, as result, because `foo().bar` existed, but `bar.baz` didn't.

In the `foo()?.bar?.baz` case, you might end up having `foo().bar`, because
`bar.baz` didn't exist.

But what if you are not interested in the whole chain, but only in a main
specific point in such chain? In that case you would have `foo()?.bar.baz
?? foo()`, but you wouldn't know how to obtain that via `foo()?.bar?.baz ??
foo()`, because the latest one might result into `foo().bar`.

Moreover, in both cases you'll end up multiplying the payload at least * 2,
while the mouse trap will work like this:

```js
foo() wrote:

> On Fri, Sep 6, 2019 at 8:04 AM Andrea Giammarchi
>  wrote:
> > Indeed I'm not super convinced myself about the "branching issue" 'cause
> `const result = this?.is?.branching?.already` and all I am proposing is to
> hint the syntax where to stop in case something else fails down the line,
> as in `const result = this.?.is part is not reached, there is a certain point to keep going (which is,
> example, checking that `result !== this`)
>
> Important distinction there is that ?. only "branches" between the
> intended type and undefined, not between two arbitrary types. The
> cognitive load between those two is significantly different.
>
> In particular, you can't *do* anything with undefined, so
> `foo?.bar.baz` has pretty unambiguous semantics - you don't think you
> might be accessing the .baz property of undefined, because that
> clearly doesn't exist.
>
> That's not the case with mouse, where it's not clear, at least to me,
> whether `foo `foo.bar.baz ? foo.bar.baz : foo` or even `foo.bar ? foo.bar.baz :
> foo`. All three seem at least somewhat reasonable, and definitely
> *believable* as an interpretation!
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Optional chaining syntax but with the "mice" operator ?

2019-09-06 Thread Andrea Giammarchi
It's 

On Fri, Sep 6, 2019, 20:14 Jordan Harband  wrote:

> Syntactically marking, in a chain, what you'd like the final value of the
> chain to be, seems interesting - forcing optionality into it seems
> unnecessary, though, if such a syntactic marker could be attached to all
> forms of property access.
>
> Something like: `a.b>.c.d` or `a?.b>?.c?.d` or `a>[b][c][d]`.
>
> (Obviously, the `>` won't work with bracket, and any syntax for normal
> properties that only applies to dot and not also bracket would somewhat be
> a nonstarter; but the specific syntax can be bikeshedded separately)
>
> On Fri, Sep 6, 2019 at 8:04 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> Indeed I'm not super convinced myself about the "branching issue" 'cause
>> `const result = this?.is?.branching?.already` and all I am proposing is to
>> hint the syntax where to stop in case something else fails down the line,
>> as in `const result = this.?.is> part is not reached, there is a certain point to keep going (which is,
>> example, checking that `result !== this`)
>>
>> On Fri, Sep 6, 2019 at 4:17 PM Naveen Chawla 
>> wrote:
>>
>>> Typically, "dot" expressions navigate through values of different types,
>>> making "type branching" the inevitable next step in those cases (unless you
>>> introduce a common method for further processing for each of those types).
>>> So I'm not sure how ultimately that would be avoided.
>>>
>>> On Fri, 6 Sep 2019 at 14:15, Claude Pache 
>>> wrote:
>>>
>>>>
>>>>
>>>> Le 6 sept. 2019 à 14:35, Felipe Nascimento de Moura <
>>>> felipenmo...@gmail.com> a écrit :
>>>>
>>>> Doesn't that bring risks to breaking the web?
>>>>
>>>> You seen, many, MANY servers running php have the "shot-tags" feature
>>>> enabled, in which pages with  will be interpreted.
>>>> In this case, any html page with embedded scripts using this operator,
>>>> or event .js files when the server is configured to also run php in them,
>>>> will break.
>>>>
>>>> Or am I missing something here?
>>>>
>>>> [ ]s
>>>>
>>>>
>>>> Any future PHP file that incorporate that syntax will almost surely
>>>> refuse to compile on servers that has short-tags enabled, making the
>>>> problem evident before it produces something useful on the web. This may be
>>>> an issue, but this is not what “breaking the web” is intended to mean.
>>>> Existing, untouched content will not break. Carelessly updated content
>>>> might break, but that’s not fundamentally different from any other careless
>>>> update.
>>>>
>>>> (If anything else, it may convince people that having different
>>>> configuration settings w.r.t. short-tags in development environment and in
>>>> production environment, is a very bad idea...)
>>>>
>>>> —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
>>>
>> ___
>> 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: Optional chaining syntax but with the "mice" operator ?

2019-09-06 Thread Andrea Giammarchi
Indeed I'm not super convinced myself about the "branching issue" 'cause
`const result = this?.is?.branching?.already` and all I am proposing is to
hint the syntax where to stop in case something else fails down the line,
as in `const result = this.?.is wrote:

> Typically, "dot" expressions navigate through values of different types,
> making "type branching" the inevitable next step in those cases (unless you
> introduce a common method for further processing for each of those types).
> So I'm not sure how ultimately that would be avoided.
>
> On Fri, 6 Sep 2019 at 14:15, Claude Pache  wrote:
>
>>
>>
>> Le 6 sept. 2019 à 14:35, Felipe Nascimento de Moura <
>> felipenmo...@gmail.com> a écrit :
>>
>> Doesn't that bring risks to breaking the web?
>>
>> You seen, many, MANY servers running php have the "shot-tags" feature
>> enabled, in which pages with  will be interpreted.
>> In this case, any html page with embedded scripts using this operator, or
>> event .js files when the server is configured to also run php in them, will
>> break.
>>
>> Or am I missing something here?
>>
>> [ ]s
>>
>>
>> Any future PHP file that incorporate that syntax will almost surely
>> refuse to compile on servers that has short-tags enabled, making the
>> problem evident before it produces something useful on the web. This may be
>> an issue, but this is not what “breaking the web” is intended to mean.
>> Existing, untouched content will not break. Carelessly updated content
>> might break, but that’s not fundamentally different from any other careless
>> update.
>>
>> (If anything else, it may convince people that having different
>> configuration settings w.r.t. short-tags in development environment and in
>> production environment, is a very bad idea...)
>>
>> —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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Optional chaining syntax but with the "mice" operator ?

2019-09-06 Thread Andrea Giammarchi
You keep diverging from the intent, basing your answers on my quick'n'dirty
examples. I agree my examples are probably not the best looking, but there
are no solutions right now to retrieve one part of th echain that failed,
if not repeating the chain, and eventually thesame errors, on the right
hand side.

This is what `https://github.com/WebReflection/mice.trap#readme

On Fri, Sep 6, 2019 at 2:48 PM Naveen Chawla  wrote:

>
> I'm not in TC39, sorry if I sounded like I was, just voicing my opinion.
>
> I think the example you gave is better served by throwing the exception
> from inside "query", instead of doing a "typeof" with the proposed operator
> afterward.
>
> I find "type branching" normally to be a cumbersome logical flow.
> Ordinarily the branching can be factored into a common "method" between the
> types, so that logical flow doesn't need the branching at all (the method
> "override" does it for you), but in the case of a "mouse" operator, you
> could often be dealing with completely different types, for which a "common
> method" may not make sense in the logical flow, thereby necessitating the
> "type branching" featured in all your examples so far.
>
> To me "type branching" is a non-communicative style of programming. The
> reader may not know the exact "type" of a particular property or
> method/function's return value, even more so in JavaScript. Even worse if
> the method may return different types depending on conditions. It is this
> lack of clarity that I think can introduce bugs. The remedy, in my mind, is
> a consistent (non-branching) logical flow. I think that language constructs
> should encourage that type of programming and discourage type branching
> (and other patterns that risk having a lack of logical clarity).
>
> Just my opinion, as I said. Disagreements welcome.
>
> On Fri, 6 Sep 2019 at 08:59, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> The purpose is to address what chaining lacks, in terms of "stopping" at
>> some point whenever it's available or not.
>>
>> Take this example:
>>
>> ```js
>> // the current chaining operator
>> const result = nmsp.some.payload()?.result ?? nmsp.some.payload();
>>
>> // the mouse operator
>> const result = nmsp.some.payload()> ```
>>
>> Keeping it semantic, the mouse operator is "a trap" for the chain that
>> makes reading possible expensive parts of the chain easier. An utility to
>> obtain the same code would look something like the following:
>>
>> ```js
>> // the mouse utility
>> const mouse = trap => {
>>   // a way to self clean right after, as it is for RegExp.$* values
>>   // which is something impossible to obtain with regular syntax
>>   Promise.resolve(mouse.trap = trap).then(() => delete mouse.trap);
>>   return trap;
>> };
>>
>> // the previous example
>> const result = mouse(nmsp.some.payload())?.result ?? mouse.trap;
>> ```
>>
>> Since there is no easy way to syntactically obtain the same with the
>> current `?` and `??` without repeating all steps in the right side of the
>> `??`, I've thought this "mouse operator" would play a role to actually
>> avoid bugs easily introduced by repeating calls on the right hand side of
>> the `??` either via getters or expensive operations.
>>
>> It is also possible to keep going on a chain or eventually provide
>> feedbacks of what went wrong:
>>
>> ```js
>> const name = await some.query(id)> if (typeof name !== 'string')
>>   throw name;
>> ```
>>
>> As summary, considering how semantic it's the operator in both visual and
>> practical meanings, and considering it's not possible to achieve the same
>> result through `??`, I wish it would be considered as complementary help
>> for the recently introduced `?.` and `??` syntax.
>>
>> So thanks in advance for possible consideration.
>>
>> Regards
>>
>>
>> On Fri, Sep 6, 2019 at 9:14 AM Naveen Chawla 
>> wrote:
>>
>>> I think introducing this operator encourages bad logic design like
>>> "instanceof", isArray etc. These are unreadable disambiguation factors in
>>> that they don't inform about which part the expression is going to the next
>>> stage in the process. Also it leads to "type branching", which tends
>>> towards more convoluted logical flow. These things, in my mind, would lead
>>> to more bugs. Hence I would ten

Re: Optional chaining syntax but with the "mice" operator ?

2019-09-06 Thread Andrea Giammarchi
The purpose is to address what chaining lacks, in terms of "stopping" at
some point whenever it's available or not.

Take this example:

```js
// the current chaining operator
const result = nmsp.some.payload()?.result ?? nmsp.some.payload();

// the mouse operator
const result = nmsp.some.payload() {
  // a way to self clean right after, as it is for RegExp.$* values
  // which is something impossible to obtain with regular syntax
  Promise.resolve(mouse.trap = trap).then(() => delete mouse.trap);
  return trap;
};

// the previous example
const result = mouse(nmsp.some.payload())?.result ?? mouse.trap;
```

Since there is no easy way to syntactically obtain the same with the
current `?` and `??` without repeating all steps in the right side of the
`??`, I've thought this "mouse operator" would play a role to actually
avoid bugs easily introduced by repeating calls on the right hand side of
the `??` either via getters or expensive operations.

It is also possible to keep going on a chain or eventually provide
feedbacks of what went wrong:

```js
const name = await some.query(id) wrote:

> I think introducing this operator encourages bad logic design like
> "instanceof", isArray etc. These are unreadable disambiguation factors in
> that they don't inform about which part the expression is going to the next
> stage in the process. Also it leads to "type branching", which tends
> towards more convoluted logical flow. These things, in my mind, would lead
> to more bugs. Hence I would tend to be against introducing it, especially
> in light of other proposals that I find more useful that haven't been taken
> even to discussion.
>
> On Fri, 6 Sep 2019, 07:58 Claude Pache,  wrote:
>
>>
>>
>> Le 5 sept. 2019 à 23:39, Andrea Giammarchi 
>> a écrit :
>>
>> This is basically a solution to a common problem we have these days,
>> where modules published in the wild might have a `default` property, to
>> support ESM logic, or not.
>>
>> ```js
>> // current optional chaining logic
>> const imported = exported?.default ?? exported;
>>
>> // my "mice operator" proposal
>> const imported = exported> ```
>>
>>
>>
>> The semantics of the `?.` in `exported?.default` is not to check whether
>> the `default` property exists, but whether `exported` evaluates to
>> undefined or null. If the `default` property is absent, `exported.default`
>> has always evaluated to `undefined`, and there is no need to optional
>> chaining operator. So that I guess you actually meant:
>>
>> ``js
>> const imported = exported.default ?? exported;
>> ```
>>
>>
>> —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: Optional chaining syntax but with the "mice" operator ?

2019-09-05 Thread Andrea Giammarchi
As someone noticed already, the operator should be called eventually
"mouse" operator, as mice is plural and was a misunderstand of mine 😅

On Fri, Sep 6, 2019, 00:54 Andrea Giammarchi 
wrote:

> Since somebody asked me already elsewhere about the expected precedence of
> the operator, this would be my answer:
>
> ```js
> const result = await dbQuery(data) ```
>
> would be the equivalent of
>
> ```js
> let result = await dbQuery(data);
> if (result != null && result.rows != null)
>   result = result.rows;
> ```
>
> or to better answer about precedence:
>
> ```js
> const result = (await dbQuery(data)) ```
>
> I hope this adds some extra context to this proposal.
>
>
> On Fri, Sep 6, 2019 at 12:28 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> absolutely, I'm working with PostgreSQL these days and indeed for any
>> promise/awaited result this pattern looks like a win, and while it's
>> targeting a limitation of the chaining one, it can be used in various other
>> cases where knowing the initial result is more important than just falling
>> back to "_dunnoWhatHappenedThere_"
>>
>> On Fri, Sep 6, 2019 at 12:24 AM Michael Luder-Rosefield <
>> rosyatran...@gmail.com> wrote:
>>
>>> Another pattern it could be useful in is with, say, nosql dbs where
>>> something might be an object or id reference:
>>>
>>> ```
>>> const fooId = foo>> ```
>>>
>>> On Thu, 5 Sep 2019, 23:03 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> Another use case that I believe will be common is the following one:
>>>>
>>>> ```js
>>>> // current state of the art
>>>> const result = dbQuery(data)?.rows ?? 'did it just failed or what?';
>>>>
>>>> // VS the "mice operator"
>>>> const result = dbQuery(data)>>>
>>>> // if it was rows
>>>> if (Array.isArray(result))
>>>>   console.log(result);
>>>> else if (result instanceof Error)
>>>>   console.error(result.message);
>>>> else
>>>>   console.warn(`unexpected result: ${result}`);
>>>> ```
>>>>
>>>> Ideally, the "mice" should grant chaining up to its latest presence,
>>>> but I wouldn't know right now how to reference to it ...
>>>>
>>>> ```js
>>>> // if no ?? is needed, this might work
>>>> const result = dbQuery(data)>>>
>>>> // if ?? is needed, no idea how to back-reference the latest
>>>> successfull "mice" result
>>>> ```
>>>>
>>>>
>>>>
>>>>
>>>> On Thu, Sep 5, 2019 at 11:44 PM Tab Atkins Jr. 
>>>> wrote:
>>>>
>>>>> On Thu, Sep 5, 2019 at 2:39 PM Andrea Giammarchi
>>>>>  wrote:
>>>>> >
>>>>> > This is basically a solution to a common problem we have these days,
>>>>> where modules published in the wild might have a `default` property, to
>>>>> support ESM logic, or not.
>>>>> >
>>>>> > ```js
>>>>> > // current optional chaining logic
>>>>> > const imported = exported?.default ?? exported;
>>>>> >
>>>>> > // my "mice operator" proposal
>>>>> > const imported = exported>>>> > ```
>>>>> >
>>>>> > Semantically speaking, not only `>>>> also points at its previous value in case the chaining didn't work.
>>>>> >
>>>>> > Beside the basic example, the "mice operator" might save CPU cycles
>>>>> when it comes to involving more complex expressions, i.e.
>>>>> >
>>>>> > ```js
>>>>> > // current "solution"
>>>>> > const thing = require('thing')?.default ?? require('thing');
>>>>> >
>>>>> > // mice operator
>>>>> > const thing = require('thing')>>>> > ```
>>>>> >
>>>>> > This is also easily tranpilable, so kinda a no-brainer for modern
>>>>> dev tools to bring in.
>>>>> >
>>>>> > TL;DR specially for cases where an accessed property should fallback
>>>>> to its source, this operator might save both typing and CPU time whenever
>>>>> it's needed.
>>>>>
>>>>> I find it a rather curious pattern, that I'd never seen before! Is it
>>>>> used in anything besides this ESM-compat thing you're talking about?
>>>>>
>>>>> (Saving CPU cycles is not a convincing argument; it's trivial to write
>>>>> such a line over two declarations and avoid any expensive
>>>>> recomputations.)
>>>>>
>>>>> ~TJ
>>>>>
>>>> ___
>>>> 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: Optional chaining syntax but with the "mice" operator ?

2019-09-05 Thread Andrea Giammarchi
Since somebody asked me already elsewhere about the expected precedence of
the operator, this would be my answer:

```js
const result = await dbQuery(data) wrote:

> absolutely, I'm working with PostgreSQL these days and indeed for any
> promise/awaited result this pattern looks like a win, and while it's
> targeting a limitation of the chaining one, it can be used in various other
> cases where knowing the initial result is more important than just falling
> back to "_dunnoWhatHappenedThere_"
>
> On Fri, Sep 6, 2019 at 12:24 AM Michael Luder-Rosefield <
> rosyatran...@gmail.com> wrote:
>
>> Another pattern it could be useful in is with, say, nosql dbs where
>> something might be an object or id reference:
>>
>> ```
>> const fooId = foo> ```
>>
>> On Thu, 5 Sep 2019, 23:03 Andrea Giammarchi, 
>> wrote:
>>
>>> Another use case that I believe will be common is the following one:
>>>
>>> ```js
>>> // current state of the art
>>> const result = dbQuery(data)?.rows ?? 'did it just failed or what?';
>>>
>>> // VS the "mice operator"
>>> const result = dbQuery(data)>>
>>> // if it was rows
>>> if (Array.isArray(result))
>>>   console.log(result);
>>> else if (result instanceof Error)
>>>   console.error(result.message);
>>> else
>>>   console.warn(`unexpected result: ${result}`);
>>> ```
>>>
>>> Ideally, the "mice" should grant chaining up to its latest presence, but
>>> I wouldn't know right now how to reference to it ...
>>>
>>> ```js
>>> // if no ?? is needed, this might work
>>> const result = dbQuery(data)>>
>>> // if ?? is needed, no idea how to back-reference the latest successfull
>>> "mice" result
>>> ```
>>>
>>>
>>>
>>>
>>> On Thu, Sep 5, 2019 at 11:44 PM Tab Atkins Jr. 
>>> wrote:
>>>
>>>> On Thu, Sep 5, 2019 at 2:39 PM Andrea Giammarchi
>>>>  wrote:
>>>> >
>>>> > This is basically a solution to a common problem we have these days,
>>>> where modules published in the wild might have a `default` property, to
>>>> support ESM logic, or not.
>>>> >
>>>> > ```js
>>>> > // current optional chaining logic
>>>> > const imported = exported?.default ?? exported;
>>>> >
>>>> > // my "mice operator" proposal
>>>> > const imported = exported>>> > ```
>>>> >
>>>> > Semantically speaking, not only `>>> also points at its previous value in case the chaining didn't work.
>>>> >
>>>> > Beside the basic example, the "mice operator" might save CPU cycles
>>>> when it comes to involving more complex expressions, i.e.
>>>> >
>>>> > ```js
>>>> > // current "solution"
>>>> > const thing = require('thing')?.default ?? require('thing');
>>>> >
>>>> > // mice operator
>>>> > const thing = require('thing')>>> > ```
>>>> >
>>>> > This is also easily tranpilable, so kinda a no-brainer for modern dev
>>>> tools to bring in.
>>>> >
>>>> > TL;DR specially for cases where an accessed property should fallback
>>>> to its source, this operator might save both typing and CPU time whenever
>>>> it's needed.
>>>>
>>>> I find it a rather curious pattern, that I'd never seen before! Is it
>>>> used in anything besides this ESM-compat thing you're talking about?
>>>>
>>>> (Saving CPU cycles is not a convincing argument; it's trivial to write
>>>> such a line over two declarations and avoid any expensive
>>>> recomputations.)
>>>>
>>>> ~TJ
>>>>
>>> ___
>>> 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: Optional chaining syntax but with the "mice" operator ?

2019-09-05 Thread Andrea Giammarchi
absolutely, I'm working with PostgreSQL these days and indeed for any
promise/awaited result this pattern looks like a win, and while it's
targeting a limitation of the chaining one, it can be used in various other
cases where knowing the initial result is more important than just falling
back to "_dunnoWhatHappenedThere_"

On Fri, Sep 6, 2019 at 12:24 AM Michael Luder-Rosefield <
rosyatran...@gmail.com> wrote:

> Another pattern it could be useful in is with, say, nosql dbs where
> something might be an object or id reference:
>
> ```
> const fooId = foo ```
>
> On Thu, 5 Sep 2019, 23:03 Andrea Giammarchi, 
> wrote:
>
>> Another use case that I believe will be common is the following one:
>>
>> ```js
>> // current state of the art
>> const result = dbQuery(data)?.rows ?? 'did it just failed or what?';
>>
>> // VS the "mice operator"
>> const result = dbQuery(data)>
>> // if it was rows
>> if (Array.isArray(result))
>>   console.log(result);
>> else if (result instanceof Error)
>>   console.error(result.message);
>> else
>>   console.warn(`unexpected result: ${result}`);
>> ```
>>
>> Ideally, the "mice" should grant chaining up to its latest presence, but
>> I wouldn't know right now how to reference to it ...
>>
>> ```js
>> // if no ?? is needed, this might work
>> const result = dbQuery(data)>
>> // if ?? is needed, no idea how to back-reference the latest successfull
>> "mice" result
>> ```
>>
>>
>>
>>
>> On Thu, Sep 5, 2019 at 11:44 PM Tab Atkins Jr. 
>> wrote:
>>
>>> On Thu, Sep 5, 2019 at 2:39 PM Andrea Giammarchi
>>>  wrote:
>>> >
>>> > This is basically a solution to a common problem we have these days,
>>> where modules published in the wild might have a `default` property, to
>>> support ESM logic, or not.
>>> >
>>> > ```js
>>> > // current optional chaining logic
>>> > const imported = exported?.default ?? exported;
>>> >
>>> > // my "mice operator" proposal
>>> > const imported = exported>> > ```
>>> >
>>> > Semantically speaking, not only `>> also points at its previous value in case the chaining didn't work.
>>> >
>>> > Beside the basic example, the "mice operator" might save CPU cycles
>>> when it comes to involving more complex expressions, i.e.
>>> >
>>> > ```js
>>> > // current "solution"
>>> > const thing = require('thing')?.default ?? require('thing');
>>> >
>>> > // mice operator
>>> > const thing = require('thing')>> > ```
>>> >
>>> > This is also easily tranpilable, so kinda a no-brainer for modern dev
>>> tools to bring in.
>>> >
>>> > TL;DR specially for cases where an accessed property should fallback
>>> to its source, this operator might save both typing and CPU time whenever
>>> it's needed.
>>>
>>> I find it a rather curious pattern, that I'd never seen before! Is it
>>> used in anything besides this ESM-compat thing you're talking about?
>>>
>>> (Saving CPU cycles is not a convincing argument; it's trivial to write
>>> such a line over two declarations and avoid any expensive
>>> recomputations.)
>>>
>>> ~TJ
>>>
>> ___
>> 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: Optional chaining syntax but with the "mice" operator ?

2019-09-05 Thread Andrea Giammarchi
Another use case that I believe will be common is the following one:

```js
// current state of the art
const result = dbQuery(data)?.rows ?? 'did it just failed or what?';

// VS the "mice operator"
const result = dbQuery(data) wrote:

> On Thu, Sep 5, 2019 at 2:39 PM Andrea Giammarchi
>  wrote:
> >
> > This is basically a solution to a common problem we have these days,
> where modules published in the wild might have a `default` property, to
> support ESM logic, or not.
> >
> > ```js
> > // current optional chaining logic
> > const imported = exported?.default ?? exported;
> >
> > // my "mice operator" proposal
> > const imported = exported > ```
> >
> > Semantically speaking, not only ` points at its previous value in case the chaining didn't work.
> >
> > Beside the basic example, the "mice operator" might save CPU cycles when
> it comes to involving more complex expressions, i.e.
> >
> > ```js
> > // current "solution"
> > const thing = require('thing')?.default ?? require('thing');
> >
> > // mice operator
> > const thing = require('thing') > ```
> >
> > This is also easily tranpilable, so kinda a no-brainer for modern dev
> tools to bring in.
> >
> > TL;DR specially for cases where an accessed property should fallback to
> its source, this operator might save both typing and CPU time whenever it's
> needed.
>
> I find it a rather curious pattern, that I'd never seen before! Is it
> used in anything besides this ESM-compat thing you're talking about?
>
> (Saving CPU cycles is not a convincing argument; it's trivial to write
> such a line over two declarations and avoid any expensive
> recomputations.)
>
> ~TJ
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Optional chaining syntax but with the "mice" operator ?

2019-09-05 Thread Andrea Giammarchi
This is basically a solution to a common problem we have these days, where
modules published in the wild might have a `default` property, to support
ESM logic, or not.

```js
// current optional chaining logic
const imported = exported?.default ?? exported;

// my "mice operator" proposal
const imported = exported___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.joinWith(iterable)

2019-08-19 Thread Andrea Giammarchi
Naveen, please read more about template literals tags, thanks.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates

On Mon, Aug 19, 2019 at 12:16 PM Naveen Chawla 
wrote:

> HTML tags? Afraid I still don't get that aspect. Perhaps my reading style
> is not matching your writing style. I understood everything else. I would
> still need a really simple example(/s) completed with sample input data
> from start to finish (for tags).
>
> Anyway from what I'm seeing so far I think "weave" is a better name than
> "joinWith".
>
> On Mon, 19 Aug 2019 at 09:56, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> A lot of libraries flatten template tags for a reason or another. The JSX
>> oriented `htm` project [1], as example, does that to obtain a single key,
>> since TypeScript has broken template literals, and avoiding duplicated work
>> per same literal is a common template tag based libraries use case.
>>
>> Here the code:
>> https://github.com/developit/htm/blob/master/src/index.mjs#L25-L31
>>
>> That could be `template[0].length + '-' +
>> template.joinWith(template.map(chunk => chunk.length + '-'))`
>>
>> Dummy no-op functions (this is only an example
>> https://github.com/WebReflection/i18n-dummy/blob/master/esm/main.js) are
>> also common, + I've used myself the pattern over and over in various
>> occasions, where you can use a generic function either as regular or as a
>> tag.
>>
>> Accordingly, the simplification would be handy already, and extra use
>> cases, as the one used with the date separator, or any other similar one,
>> shows possible new ways to easily join arbitrary amount of data.
>>
>> Because of these previous points, I've thought proposing this was worth a
>> shot.
>>
>> [1] https://github.com/developit/htm
>>
>>
>> On Fri, Aug 16, 2019 at 10:00 PM Jordan Harband  wrote:
>>
>>> Can you elaborate a bit more on how this is a *common* case in the wider
>>> ecosystem?
>>>
>>> On Fri, Aug 16, 2019 at 5:29 AM Andrea Giammarchi <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> early reply  "which otehr cases"? this is just an example:
>>>>
>>>> [2019, 08, 16, 14, 28, 30].map(i => i < 10 ? ('0' + i) :
>>>> i).joinWith('--T::.');
>>>>
>>>> On Fri, Aug 16, 2019 at 2:24 PM Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> `this ${Symbol('throws')} an error`, so anything that cannot be
>>>>> represented as string should throw too, as it is for `[1, 2,
>>>>> 3].join(Symbol())`.
>>>>>
>>>>> In few words, everything described as parameter for the
>>>>> `Array.prototype.join(param)` should be described as the iterable value,
>>>>> nothng new to add, nothing different to expect.
>>>>>
>>>>> The template literal as is returns a string, but if you use tags, as
>>>>> functions, you deal with an array and a collection or extra values (0 to
>>>>> template.length - 1).
>>>>>
>>>>> The current way to flatten a template via tag, used already in various
>>>>> projects for a reason or another, is the following one:
>>>>>
>>>>> ```js
>>>>> function tag2str(template) {
>>>>>   let str = template[0];
>>>>>   for (let i = 1, t = template.length; i < t; i++)
>>>>> str += arguments[i] + template[i];
>>>>>   return str;
>>>>> }
>>>>> ```
>>>>>
>>>>> I am proposing to simplify this common case with something that could
>>>>> be used for other cases too.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Fri, Aug 16, 2019 at 1:17 PM Naveen Chawla 
>>>>> wrote:
>>>>>
>>>>>> Cool.
>>>>>>
>>>>>> I get it now apart from the "templated string" example. I'm not very
>>>>>> knowledgable about templated strings but on the face it looks like
>>>>>> 'a${x}b${y}' already inserts x and y into the string, so I'm not sure 
>>>>>> what
>>>>>> else is happening with your proposed method? Clearly I've missed 
>>>>

Re: Array.prototype.joinWith(iterable)

2019-08-19 Thread Andrea Giammarchi
A lot of libraries flatten template tags for a reason or another. The JSX
oriented `htm` project [1], as example, does that to obtain a single key,
since TypeScript has broken template literals, and avoiding duplicated work
per same literal is a common template tag based libraries use case.

Here the code:
https://github.com/developit/htm/blob/master/src/index.mjs#L25-L31

That could be `template[0].length + '-' +
template.joinWith(template.map(chunk => chunk.length + '-'))`

Dummy no-op functions (this is only an example
https://github.com/WebReflection/i18n-dummy/blob/master/esm/main.js) are
also common, + I've used myself the pattern over and over in various
occasions, where you can use a generic function either as regular or as a
tag.

Accordingly, the simplification would be handy already, and extra use
cases, as the one used with the date separator, or any other similar one,
shows possible new ways to easily join arbitrary amount of data.

Because of these previous points, I've thought proposing this was worth a
shot.

[1] https://github.com/developit/htm


On Fri, Aug 16, 2019 at 10:00 PM Jordan Harband  wrote:

> Can you elaborate a bit more on how this is a *common* case in the wider
> ecosystem?
>
> On Fri, Aug 16, 2019 at 5:29 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> early reply  "which otehr cases"? this is just an example:
>>
>> [2019, 08, 16, 14, 28, 30].map(i => i < 10 ? ('0' + i) :
>> i).joinWith('--T::.');
>>
>> On Fri, Aug 16, 2019 at 2:24 PM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> `this ${Symbol('throws')} an error`, so anything that cannot be
>>> represented as string should throw too, as it is for `[1, 2,
>>> 3].join(Symbol())`.
>>>
>>> In few words, everything described as parameter for the
>>> `Array.prototype.join(param)` should be described as the iterable value,
>>> nothng new to add, nothing different to expect.
>>>
>>> The template literal as is returns a string, but if you use tags, as
>>> functions, you deal with an array and a collection or extra values (0 to
>>> template.length - 1).
>>>
>>> The current way to flatten a template via tag, used already in various
>>> projects for a reason or another, is the following one:
>>>
>>> ```js
>>> function tag2str(template) {
>>>   let str = template[0];
>>>   for (let i = 1, t = template.length; i < t; i++)
>>> str += arguments[i] + template[i];
>>>   return str;
>>> }
>>> ```
>>>
>>> I am proposing to simplify this common case with something that could be
>>> used for other cases too.
>>>
>>>
>>>
>>>
>>>
>>> On Fri, Aug 16, 2019 at 1:17 PM Naveen Chawla 
>>> wrote:
>>>
>>>> Cool.
>>>>
>>>> I get it now apart from the "templated string" example. I'm not very
>>>> knowledgable about templated strings but on the face it looks like
>>>> 'a${x}b${y}' already inserts x and y into the string, so I'm not sure what
>>>> else is happening with your proposed method? Clearly I've missed something.
>>>>
>>>> Apart from that, how would you handle arrays that whose values are not
>>>> all strings?
>>>>
>>>> For naming is still think "weave" would be OK from what I know so far
>>>>
>>>> On Fri, 16 Aug 2019 at 11:08, Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> given an array, it joins it through the values of the iterable
>>>>> argument, without ever resulting to undefined
>>>>>
>>>>> ['a', 'b', 'c'].joinWith(['-']) would produce "a-b-c"
>>>>>
>>>>> ['a', 'b', 'c'].joinWith([1, 2]) would produce "a1b2c"
>>>>>
>>>>> ['a', 'b', 'c'].joinWith('012') would produce "a0b1c"
>>>>> note the string, as iterable, is acceptable too
>>>>>
>>>>> const tag = (template, ...values) => template.joinWith(values);
>>>>> tag`a${Math.random()}b${Math.random()}`; would fill the gap between a
>>>>> and b, or b and c, with the value returned by the two Math.random()
>>>>>
>>>>> ['a', 'b', 'c', 'd&

Re: Array.prototype.joinWith(iterable)

2019-08-16 Thread Andrea Giammarchi
early reply  "which otehr cases"? this is just an example:

[2019, 08, 16, 14, 28, 30].map(i => i < 10 ? ('0' + i) :
i).joinWith('--T::.');

On Fri, Aug 16, 2019 at 2:24 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> `this ${Symbol('throws')} an error`, so anything that cannot be
> represented as string should throw too, as it is for `[1, 2,
> 3].join(Symbol())`.
>
> In few words, everything described as parameter for the
> `Array.prototype.join(param)` should be described as the iterable value,
> nothng new to add, nothing different to expect.
>
> The template literal as is returns a string, but if you use tags, as
> functions, you deal with an array and a collection or extra values (0 to
> template.length - 1).
>
> The current way to flatten a template via tag, used already in various
> projects for a reason or another, is the following one:
>
> ```js
> function tag2str(template) {
>   let str = template[0];
>   for (let i = 1, t = template.length; i < t; i++)
> str += arguments[i] + template[i];
>   return str;
> }
> ```
>
> I am proposing to simplify this common case with something that could be
> used for other cases too.
>
>
>
>
>
> On Fri, Aug 16, 2019 at 1:17 PM Naveen Chawla 
> wrote:
>
>> Cool.
>>
>> I get it now apart from the "templated string" example. I'm not very
>> knowledgable about templated strings but on the face it looks like
>> 'a${x}b${y}' already inserts x and y into the string, so I'm not sure what
>> else is happening with your proposed method? Clearly I've missed something.
>>
>> Apart from that, how would you handle arrays that whose values are not
>> all strings?
>>
>> For naming is still think "weave" would be OK from what I know so far
>>
>> On Fri, 16 Aug 2019 at 11:08, Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> given an array, it joins it through the values of the iterable argument,
>>> without ever resulting to undefined
>>>
>>> ['a', 'b', 'c'].joinWith(['-']) would produce "a-b-c"
>>>
>>> ['a', 'b', 'c'].joinWith([1, 2]) would produce "a1b2c"
>>>
>>> ['a', 'b', 'c'].joinWith('012') would produce "a0b1c"
>>> note the string, as iterable, is acceptable too
>>>
>>> const tag = (template, ...values) => template.joinWith(values);
>>> tag`a${Math.random()}b${Math.random()}`; would fill the gap between a
>>> and b, or b and c, with the value returned by the two Math.random()
>>>
>>> ['a', 'b', 'c', 'd'].joinWith('01'); would produce "a0b1c0d" so that
>>> there's never an `undefined
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Fri, Aug 16, 2019 at 12:01 PM Naveen Chawla 
>>> wrote:
>>>
>>>> I'm just not seeing what it's supposed to do. If you could give a brief
>>>> explanation of the array method, and the string method then of course I
>>>> would get it. I know it would seem obvious to you from the examples alone,
>>>> it's just not to me.
>>>>
>>>> On Fri, 16 Aug 2019 at 08:32, Andrea Giammarchi <
>>>> andrea.giammar...@gmail.com> wrote:
>>>>
>>>>> Just to re-state: zip from lowdash, does **not** do what my proposed
>>>>> method does ... anything that won't produce the following result is not
>>>>> what I'm proposing
>>>>>
>>>>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>>>>> // a1b2c1d
>>>>>
>>>>> function tag2str(template, ...values) {
>>>>>   return template.joinWith(values);
>>>>> }
>>>>>
>>>>> tag2str`a${1}b${2}c`;
>>>>> // "a1b2c"
>>>>>
>>>>> On Fri, Aug 16, 2019 at 5:57 AM Isiah Meadows 
>>>>> wrote:
>>>>>
>>>>>> For that, I'd rather see an `interleave` that just rotates through all
>>>>>> its arguments. It'd be basically sugar for `.zip().flat()`, but an
>>>>>> implementation could optimize the heck out of it. (In particular, they
>>>>>> could iterate through them

Re: Array.prototype.joinWith(iterable)

2019-08-16 Thread Andrea Giammarchi
`this ${Symbol('throws')} an error`, so anything that cannot be represented
as string should throw too, as it is for `[1, 2, 3].join(Symbol())`.

In few words, everything described as parameter for the
`Array.prototype.join(param)` should be described as the iterable value,
nothng new to add, nothing different to expect.

The template literal as is returns a string, but if you use tags, as
functions, you deal with an array and a collection or extra values (0 to
template.length - 1).

The current way to flatten a template via tag, used already in various
projects for a reason or another, is the following one:

```js
function tag2str(template) {
  let str = template[0];
  for (let i = 1, t = template.length; i < t; i++)
str += arguments[i] + template[i];
  return str;
}
```

I am proposing to simplify this common case with something that could be
used for other cases too.





On Fri, Aug 16, 2019 at 1:17 PM Naveen Chawla  wrote:

> Cool.
>
> I get it now apart from the "templated string" example. I'm not very
> knowledgable about templated strings but on the face it looks like
> 'a${x}b${y}' already inserts x and y into the string, so I'm not sure what
> else is happening with your proposed method? Clearly I've missed something.
>
> Apart from that, how would you handle arrays that whose values are not all
> strings?
>
> For naming is still think "weave" would be OK from what I know so far
>
> On Fri, 16 Aug 2019 at 11:08, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> given an array, it joins it through the values of the iterable argument,
>> without ever resulting to undefined
>>
>> ['a', 'b', 'c'].joinWith(['-']) would produce "a-b-c"
>>
>> ['a', 'b', 'c'].joinWith([1, 2]) would produce "a1b2c"
>>
>> ['a', 'b', 'c'].joinWith('012') would produce "a0b1c"
>> note the string, as iterable, is acceptable too
>>
>> const tag = (template, ...values) => template.joinWith(values);
>> tag`a${Math.random()}b${Math.random()}`; would fill the gap between a and
>> b, or b and c, with the value returned by the two Math.random()
>>
>> ['a', 'b', 'c', 'd'].joinWith('01'); would produce "a0b1c0d" so that
>> there's never an `undefined
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Fri, Aug 16, 2019 at 12:01 PM Naveen Chawla 
>> wrote:
>>
>>> I'm just not seeing what it's supposed to do. If you could give a brief
>>> explanation of the array method, and the string method then of course I
>>> would get it. I know it would seem obvious to you from the examples alone,
>>> it's just not to me.
>>>
>>> On Fri, 16 Aug 2019 at 08:32, Andrea Giammarchi <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> Just to re-state: zip from lowdash, does **not** do what my proposed
>>>> method does ... anything that won't produce the following result is not
>>>> what I'm proposing
>>>>
>>>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>>>> // a1b2c1d
>>>>
>>>> function tag2str(template, ...values) {
>>>>   return template.joinWith(values);
>>>> }
>>>>
>>>> tag2str`a${1}b${2}c`;
>>>> // "a1b2c"
>>>>
>>>> On Fri, Aug 16, 2019 at 5:57 AM Isiah Meadows 
>>>> wrote:
>>>>
>>>>> For that, I'd rather see an `interleave` that just rotates through all
>>>>> its arguments. It'd be basically sugar for `.zip().flat()`, but an
>>>>> implementation could optimize the heck out of it. (In particular, they
>>>>> could iterate through them one-by-one and only allocate once, not in
>>>>> the hot loop, so it'd be fast.)
>>>>>
>>>>> I at one point had it in my list of wishlist proposals, but it somehow
>>>>> disappeared. I've since recreated it:
>>>>>
>>>>> https://github.com/isiahmeadows/es-stdlib-proposals/blob/master/proposals/array/interleave.md
>>>>>
>>>>> -
>>>>>
>>>>> Isiah Meadows
>>>>> cont...@isiahmeadows.com
>>>>> www.isiahmeadows.com
>>>>>
>>>>>
>>>>> On Thu, Aug 15, 2019 at 1:12 PM Andrea Giammarchi
>&g

Re: Array.prototype.joinWith(iterable)

2019-08-16 Thread Andrea Giammarchi
given an array, it joins it through the values of the iterable argument,
without ever resulting to undefined

['a', 'b', 'c'].joinWith(['-']) would produce "a-b-c"

['a', 'b', 'c'].joinWith([1, 2]) would produce "a1b2c"

['a', 'b', 'c'].joinWith('012') would produce "a0b1c"
note the string, as iterable, is acceptable too

const tag = (template, ...values) => template.joinWith(values);
tag`a${Math.random()}b${Math.random()}`; would fill the gap between a and
b, or b and c, with the value returned by the two Math.random()

['a', 'b', 'c', 'd'].joinWith('01'); would produce "a0b1c0d" so that
there's never an `undefined









On Fri, Aug 16, 2019 at 12:01 PM Naveen Chawla 
wrote:

> I'm just not seeing what it's supposed to do. If you could give a brief
> explanation of the array method, and the string method then of course I
> would get it. I know it would seem obvious to you from the examples alone,
> it's just not to me.
>
> On Fri, 16 Aug 2019 at 08:32, Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> Just to re-state: zip from lowdash, does **not** do what my proposed
>> method does ... anything that won't produce the following result is not
>> what I'm proposing
>>
>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>> // a1b2c1d
>>
>> function tag2str(template, ...values) {
>>   return template.joinWith(values);
>> }
>>
>> tag2str`a${1}b${2}c`;
>> // "a1b2c"
>>
>> On Fri, Aug 16, 2019 at 5:57 AM Isiah Meadows 
>> wrote:
>>
>>> For that, I'd rather see an `interleave` that just rotates through all
>>> its arguments. It'd be basically sugar for `.zip().flat()`, but an
>>> implementation could optimize the heck out of it. (In particular, they
>>> could iterate through them one-by-one and only allocate once, not in
>>> the hot loop, so it'd be fast.)
>>>
>>> I at one point had it in my list of wishlist proposals, but it somehow
>>> disappeared. I've since recreated it:
>>>
>>> https://github.com/isiahmeadows/es-stdlib-proposals/blob/master/proposals/array/interleave.md
>>>
>>> -
>>>
>>> Isiah Meadows
>>> cont...@isiahmeadows.com
>>> www.isiahmeadows.com
>>>
>>>
>>> On Thu, Aug 15, 2019 at 1:12 PM Andrea Giammarchi
>>>  wrote:
>>> >
>>> > That;s not useful for template literals tags though
>>> >
>>> > _.zip(['a', 'b', 'c'], [1, 2]);
>>> > [["a", 1], ["b", 2], ["c", undefined]]
>>> >
>>> > it basically does nothing I've proposed ... any other name suggestion?
>>> >
>>> > On Thu, Aug 15, 2019 at 3:40 PM Michał Wadas 
>>> wrote:
>>> >>
>>> >> https://lodash.com/docs/#zip
>>> >> https://docs.python.org/3/library/functions.html#zip
>>> >>
>>> >> On Thu, 15 Aug 2019, 15:34 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>> >>>
>>> >>> the suggested name is just ... suggested, I don't have strong
>>> opinion on it, it just `join` values through other values
>>> >>> what's `Array.zip` ? I've no idea
>>> >>>
>>> >>>
>>> >>> On Thu, Aug 15, 2019 at 12:53 PM Michał Wadas 
>>> wrote:
>>> >>>>
>>> >>>> I would rather see Array.zip, it covers this use case.
>>> >>>>
>>> >>>> On Thu, 15 Aug 2019, 10:50 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>> >>>>>
>>> >>>>>
>>> >>>>> I wonder if there's any interest in adding another handy Array
>>> method as joinWith could be:
>>> >>>>>
>>> >>>>> ```js
>>> >>>>> // proposal example
>>> >>>>> Array.prototype.joinWith = function (values) {
>>> >>>>>   const {length} = this;
>>> >>>>>   if (length < 2)
>>> >>>>> return this.join('');
>>> >>>>>   const out = [this[0]];
>>> >>>>>   const len = values.length;
>>> >>>>>   for (let i = 1; i < length; i++) {
>>> >>>>> console.log(i, len);
>>> >>>>> out.push(values[(i - 1) % len], this[i]);
>>> >>>>>   }
>>> >>>>>   return out.join('');
>>> >>>>> };
>>> >>>>> ```
>>> >>>>>
>>> >>>>> The goal is to simplify joining array entries through not the same
>>> value, example:
>>> >>>>>
>>> >>>>> ```js
>>> >>>>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>>> >>>>> // a1b2c1d
>>> >>>>>
>>> >>>>> function tag2str(template, ...values) {
>>> >>>>>   return template.joinWith(values);
>>> >>>>> }
>>> >>>>>
>>> >>>>> tag2str`a${1}b${2}c`;
>>> >>>>> // "a1b2c"
>>> >>>>> ```
>>> >>>>>
>>> >>>>> Throughts?
>>> >>>>> ___
>>> >>>>> 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
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.joinWith(iterable)

2019-08-16 Thread Andrea Giammarchi
Just to re-state: zip from lowdash, does **not** do what my proposed method
does ... anything that won't produce the following result is not what I'm
proposing

console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
// a1b2c1d

function tag2str(template, ...values) {
  return template.joinWith(values);
}

tag2str`a${1}b${2}c`;
// "a1b2c"

On Fri, Aug 16, 2019 at 5:57 AM Isiah Meadows 
wrote:

> For that, I'd rather see an `interleave` that just rotates through all
> its arguments. It'd be basically sugar for `.zip().flat()`, but an
> implementation could optimize the heck out of it. (In particular, they
> could iterate through them one-by-one and only allocate once, not in
> the hot loop, so it'd be fast.)
>
> I at one point had it in my list of wishlist proposals, but it somehow
> disappeared. I've since recreated it:
>
> https://github.com/isiahmeadows/es-stdlib-proposals/blob/master/proposals/array/interleave.md
>
> -----
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
>
>
> On Thu, Aug 15, 2019 at 1:12 PM Andrea Giammarchi
>  wrote:
> >
> > That;s not useful for template literals tags though
> >
> > _.zip(['a', 'b', 'c'], [1, 2]);
> > [["a", 1], ["b", 2], ["c", undefined]]
> >
> > it basically does nothing I've proposed ... any other name suggestion?
> >
> > On Thu, Aug 15, 2019 at 3:40 PM Michał Wadas 
> wrote:
> >>
> >> https://lodash.com/docs/#zip
> >> https://docs.python.org/3/library/functions.html#zip
> >>
> >> On Thu, 15 Aug 2019, 15:34 Andrea Giammarchi, <
> andrea.giammar...@gmail.com> wrote:
> >>>
> >>> the suggested name is just ... suggested, I don't have strong opinion
> on it, it just `join` values through other values
> >>> what's `Array.zip` ? I've no idea
> >>>
> >>>
> >>> On Thu, Aug 15, 2019 at 12:53 PM Michał Wadas 
> wrote:
> >>>>
> >>>> I would rather see Array.zip, it covers this use case.
> >>>>
> >>>> On Thu, 15 Aug 2019, 10:50 Andrea Giammarchi, <
> andrea.giammar...@gmail.com> wrote:
> >>>>>
> >>>>>
> >>>>> I wonder if there's any interest in adding another handy Array
> method as joinWith could be:
> >>>>>
> >>>>> ```js
> >>>>> // proposal example
> >>>>> Array.prototype.joinWith = function (values) {
> >>>>>   const {length} = this;
> >>>>>   if (length < 2)
> >>>>> return this.join('');
> >>>>>   const out = [this[0]];
> >>>>>   const len = values.length;
> >>>>>   for (let i = 1; i < length; i++) {
> >>>>> console.log(i, len);
> >>>>> out.push(values[(i - 1) % len], this[i]);
> >>>>>   }
> >>>>>   return out.join('');
> >>>>> };
> >>>>> ```
> >>>>>
> >>>>> The goal is to simplify joining array entries through not the same
> value, example:
> >>>>>
> >>>>> ```js
> >>>>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
> >>>>> // a1b2c1d
> >>>>>
> >>>>> function tag2str(template, ...values) {
> >>>>>   return template.joinWith(values);
> >>>>> }
> >>>>>
> >>>>> tag2str`a${1}b${2}c`;
> >>>>> // "a1b2c"
> >>>>> ```
> >>>>>
> >>>>> Throughts?
> >>>>> ___
> >>>>> 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.findIndex(fn, startIndex = 0)

2019-08-15 Thread Andrea Giammarchi
isn't the second argument already reserved for the context?

```js
[1, 2, 3].findIndex(function (i) { return i == this; }, 2);
// 1
```

On Thu, Aug 15, 2019 at 11:51 PM Cyril Auburtin 
wrote:

> It should be possible to add a second optional argument to the `find` and
> `findIndex` array methods, similarly to `indexOf`
> ___
> 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.joinWith(iterable)

2019-08-15 Thread Andrea Giammarchi
There is a whole example that produces a string, like join does, using the
second argument iterable to fill the "junctions" ... which part is not
clear in the test case?

```js
console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
// a1b2c1d

function tag2str(template, ...values) {
  return template.joinWith(values);
}

tag2str`a${1}b${2}c`;
// "a1b2c"
```

On Thu, Aug 15, 2019 at 7:39 PM Naveen Chawla  wrote:

> "weave"? (I've likely missed the purpose of the method)
>
> On Thu, 15 Aug 2019, 18:12 Andrea Giammarchi, 
> wrote:
>
>> That;s not useful for template literals tags though
>>
>> _.zip(['a', 'b', 'c'], [1, 2]);
>> [["a", 1], ["b", 2], ["c", undefined]]
>>
>> it basically does nothing I've proposed ... any other name suggestion?
>>
>> On Thu, Aug 15, 2019 at 3:40 PM Michał Wadas 
>> wrote:
>>
>>> https://lodash.com/docs/#zip
>>> https://docs.python.org/3/library/functions.html#zip
>>>
>>> On Thu, 15 Aug 2019, 15:34 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>>
>>>>1. the suggested name is just ... suggested, I don't have strong
>>>>opinion on it, it just `join` values through other values
>>>>2. what's `Array.zip` ? I've no idea
>>>>
>>>>
>>>> On Thu, Aug 15, 2019 at 12:53 PM Michał Wadas 
>>>> wrote:
>>>>
>>>>> I would rather see Array.zip, it covers this use case.
>>>>>
>>>>> On Thu, 15 Aug 2019, 10:50 Andrea Giammarchi, <
>>>>> andrea.giammar...@gmail.com> wrote:
>>>>>
>>>>>>
>>>>>> I wonder if there's any interest in adding another handy Array method
>>>>>> as joinWith could be:
>>>>>>
>>>>>> ```js
>>>>>> // proposal example
>>>>>> Array.prototype.joinWith = function (values) {
>>>>>>   const {length} = this;
>>>>>>   if (length < 2)
>>>>>> return this.join('');
>>>>>>   const out = [this[0]];
>>>>>>   const len = values.length;
>>>>>>   for (let i = 1; i < length; i++) {
>>>>>> console.log(i, len);
>>>>>> out.push(values[(i - 1) % len], this[i]);
>>>>>>   }
>>>>>>   return out.join('');
>>>>>> };
>>>>>> ```
>>>>>>
>>>>>> The goal is to simplify joining array entries through not the same
>>>>>> value, example:
>>>>>>
>>>>>> ```js
>>>>>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>>>>>> // a1b2c1d
>>>>>>
>>>>>> function tag2str(template, ...values) {
>>>>>>   return template.joinWith(values);
>>>>>> }
>>>>>>
>>>>>> tag2str`a${1}b${2}c`;
>>>>>> // "a1b2c"
>>>>>> ```
>>>>>>
>>>>>> Throughts?
>>>>>> ___
>>>>>> 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: Modulo Operator %%

2019-08-15 Thread Andrea Giammarchi
Fair points, but since `**` has its `Math.pow` counter part, why wouldn't
`%%` have `Math.mod` as counterpart too? At least it looks like there's
room for both, if standardized, as the behavior and description would
likely be mostly the same (precedence a part)

On Thu, Aug 15, 2019 at 7:13 PM Isiah Meadows 
wrote:

> An operator is far more concise than a function call, and is likely to
> see greater use. It also aligns better with peoples' intuition on what
> the "modulus" is, avoiding subtle bugs like in `isOdd = x => x % 2 ===
> 1` (example from
> https://en.wikipedia.org/wiki/Modulo_operation#Common_pitfalls - try
> passing a negative to it). And given this one is high value (see
> above) and *very* low cost (it can literally desugar to `(x % y + y) %
> y`), I feel it does meet that bar.
>
> > It would be interesting to hear the feedback of those that use regularly
> powers, whether the benefit was clear (personally, I almost never use
> either `Math.pow()` or `**`, so that I can’t say anything).
>
> It has enough benefit I've seen CoffeeScript users default to `%%` and
> only using `%` when they explicitly want the dividend-dependent
> semantics. And engines with a native `%%`, if they can detect the
> operands are always non-negative, can optimize it to `%` pretty
> easily. It's better *enough* that you'd likely start seeing some
> partially legitimate FUD spread about the standard `%`.
>
> One other added benefit of using divisor-dependent modulo is that `x
> %% (2**n)`, where `x` and `n` are integers and `n >= 0`, could always
> be safely rewritten to `x & (2**n - 1)` while still preserving
> semantics, but `x % (2**n)` does *not* have this property. For
> example:
>
> - `-1 %% (2**1)` → `-1 %% 1` → `1`
> - `-1 & (2**1 - 1)` → `-1 & 1` → `1`
> - `-1 % (2**1)` → `-1 % 2` → `-1`
>
> BTW, I literally tested all three of these in Chrome's devtools
> console, using my `x %% y` → `(x % y + y) % y` desugaring.
>
> As for a native implementation and the spec, I'd recommend just doing
> `copysign(fmod(x, y), y)` instead to retain precision.
>
> > At least one disadvantage of an operator over a function, is that you
> have to think about precedence. The problem is exacerbated in JS, because
> (following some other languages) the unary minus has an uncanny high
> precedence level, confusingly very different than the one of the binary
> minus; so that, after having designed `**`, it was realised at the last
> minute that `-a**b` would be dumbly interpreted as `(-a)**b` instead of
> `-(a**b)` or `0-a**b`, as anybody who would be likely to actually use the
> operator would expect. (That particular issue was resolved in a hurry by
> making the parenthesis-left form a syntax error.)
>
> I doubt this would happen with `%%`. It's similar enough to the
> existing `%` in concept that most would expect it to have the same
> precedence. With `**`, there was a very unique issue with it: there
> were people actually *reading* it both ways, and even a language
> (Python) that interprets `-a ** b` and `-a**b` *differently* in light
> of that (as `(-a) ** b` and `-(a ** b)` respectively). That's not a
> concern at all with most operators, so it doesn't apply to most new
> operator proposals.
>
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
> On Thu, Aug 15, 2019 at 2:40 AM Claude Pache 
> wrote:
> >
> >
> >
> > Le 12 août 2019 à 22:00, Matthew Morgan  a
> écrit :
> >
> > > JS needs a modulo operator. It currently has the remainder operator
> `%` which works in most cases except for negative values. I believe the the
> `%%` would work great and be easy to remember.
> > >
> > > let x = (-13) %% 64;
> > > is equivalent to
> > > let x = ((-13 % 64) + 64) % 64;
> >
> >
> > Is there a strong advantage of an `%%` operator over a `Math.mod()`
> function? There is the precedent of the `**` operator implemented as
> alternative of `Math.pow()` few years ago. It would be interesting to hear
> the feedback of those that use regularly powers, whether the benefit was
> clear (personally, I almost never use either `Math.pow()` or `**`, so that
> I can’t say anything).
> >
> > At least one disadvantage of an operator over a function, is that you
> have to think about precedence. The problem is exacerbated in JS, because
> (following some other languages) the unary minus has an uncanny high
> precedence level, confusingly very different than the one of the binary
> minus; so that, after having designed `**`, it was realised at the last
> minute that `-a**b` would be dumbly interpreted as `(-a)**b` instead of
> `-(a**b)` or `0-a**b`, as anybody who would be likely to actually use the
> operator would expect. (That particular issue was resolved in a hurry by
> making the parenthesis-left form a syntax error.)
> >
> > —Claude
> >
> > ___
> > es-discuss mailing list
> > es-discuss@mozilla.org
> > https://mail.mozilla.org/listinfo/es-discuss
> __

Re: Array.prototype.joinWith(iterable)

2019-08-15 Thread Andrea Giammarchi
That;s not useful for template literals tags though

_.zip(['a', 'b', 'c'], [1, 2]);
[["a", 1], ["b", 2], ["c", undefined]]

it basically does nothing I've proposed ... any other name suggestion?

On Thu, Aug 15, 2019 at 3:40 PM Michał Wadas  wrote:

> https://lodash.com/docs/#zip
> https://docs.python.org/3/library/functions.html#zip
>
> On Thu, 15 Aug 2019, 15:34 Andrea Giammarchi, 
> wrote:
>
>>
>>1. the suggested name is just ... suggested, I don't have strong
>>opinion on it, it just `join` values through other values
>>2. what's `Array.zip` ? I've no idea
>>
>>
>> On Thu, Aug 15, 2019 at 12:53 PM Michał Wadas 
>> wrote:
>>
>>> I would rather see Array.zip, it covers this use case.
>>>
>>> On Thu, 15 Aug 2019, 10:50 Andrea Giammarchi, <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>>
>>>> I wonder if there's any interest in adding another handy Array method
>>>> as joinWith could be:
>>>>
>>>> ```js
>>>> // proposal example
>>>> Array.prototype.joinWith = function (values) {
>>>>   const {length} = this;
>>>>   if (length < 2)
>>>> return this.join('');
>>>>   const out = [this[0]];
>>>>   const len = values.length;
>>>>   for (let i = 1; i < length; i++) {
>>>> console.log(i, len);
>>>> out.push(values[(i - 1) % len], this[i]);
>>>>   }
>>>>   return out.join('');
>>>> };
>>>> ```
>>>>
>>>> The goal is to simplify joining array entries through not the same
>>>> value, example:
>>>>
>>>> ```js
>>>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>>>> // a1b2c1d
>>>>
>>>> function tag2str(template, ...values) {
>>>>   return template.joinWith(values);
>>>> }
>>>>
>>>> tag2str`a${1}b${2}c`;
>>>> // "a1b2c"
>>>> ```
>>>>
>>>> Throughts?
>>>> ___
>>>> 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: Modulo Operator %%

2019-08-15 Thread Andrea Giammarchi
To me there's no risk, as MooTools, Prototype, and Scriptacolous are both
things of the past, and never implemented Math.mod ... so, with that
approach, custom transpiling functions are more dangerous, as somebody
might have implemented `%%` already for other purposes, and we break Babel
outcome adding new syntax anyway ... the smoosh accident, is the equivalent
of custom Babel utilities these days.

Look at TypeScript and the private class fields, if you want to compare new
syntax instead

On Thu, Aug 15, 2019 at 4:50 PM Michael Haufe 
wrote:

> Thursday, August 15, 2019 2:47 AM, Andrea Giammarchi wrote:
>
>
>
> > FWIW another disadvantage is that operators cannot be polyfilled, so
> it'll take forever for those not using transpilers to adopt these, while
> having a `Math,mod` would work right away
>
>
>
>
>
> With such an approach there is risk of another ‘smooshgate’ [1][2]. There
> is nothing stopping those developers from using a function anyway to bridge
> the gap if they can’t or won’t use a compiler. This is already the current
> state of affairs.
>
>
>
> [1] https://developers.google.com/web/updates/2018/03/smooshgate
>
> [2]
> https://adamsilver.io/articles/the-disadvantages-of-javascript-polyfills/
>
>
>
> Michael
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.joinWith(iterable)

2019-08-15 Thread Andrea Giammarchi
   1. the suggested name is just ... suggested, I don't have strong opinion
   on it, it just `join` values through other values
   2. what's `Array.zip` ? I've no idea


On Thu, Aug 15, 2019 at 12:53 PM Michał Wadas  wrote:

> I would rather see Array.zip, it covers this use case.
>
> On Thu, 15 Aug 2019, 10:50 Andrea Giammarchi, 
> wrote:
>
>>
>> I wonder if there's any interest in adding another handy Array method as
>> joinWith could be:
>>
>> ```js
>> // proposal example
>> Array.prototype.joinWith = function (values) {
>>   const {length} = this;
>>   if (length < 2)
>> return this.join('');
>>   const out = [this[0]];
>>   const len = values.length;
>>   for (let i = 1; i < length; i++) {
>> console.log(i, len);
>> out.push(values[(i - 1) % len], this[i]);
>>   }
>>   return out.join('');
>> };
>> ```
>>
>> The goal is to simplify joining array entries through not the same value,
>> example:
>>
>> ```js
>> console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
>> // a1b2c1d
>>
>> function tag2str(template, ...values) {
>>   return template.joinWith(values);
>> }
>>
>> tag2str`a${1}b${2}c`;
>> // "a1b2c"
>> ```
>>
>> Throughts?
>> ___
>> 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


Array.prototype.joinWith(iterable)

2019-08-15 Thread Andrea Giammarchi
I wonder if there's any interest in adding another handy Array method as
joinWith could be:

```js
// proposal example
Array.prototype.joinWith = function (values) {
  const {length} = this;
  if (length < 2)
return this.join('');
  const out = [this[0]];
  const len = values.length;
  for (let i = 1; i < length; i++) {
console.log(i, len);
out.push(values[(i - 1) % len], this[i]);
  }
  return out.join('');
};
```

The goal is to simplify joining array entries through not the same value,
example:

```js
console.log(['a', 'b', 'c', 'd'].joinWith([1, 2]));
// a1b2c1d

function tag2str(template, ...values) {
  return template.joinWith(values);
}

tag2str`a${1}b${2}c`;
// "a1b2c"
```

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


Re: Modulo Operator %%

2019-08-15 Thread Andrea Giammarchi
FWIW another disadvantage is that operators cannot be polyfilled, so it'll
take forever for those not using transpilers to adopt these, while having a
`Math,mod` would work right away

On Thu, Aug 15, 2019 at 8:40 AM Claude Pache  wrote:

>
>
> Le 12 août 2019 à 22:00, Matthew Morgan  a écrit :
>
> JS needs a modulo operator. It currently has the remainder operator `%`
> which works in most cases except for negative values. I believe the the
> `%%` would work great and be easy to remember.
>
> let x = (-13) %% 64;
> is equivalent to
> let x = ((-13 % 64) + 64) % 64;
>
>
> Is there a strong advantage of an `%%` operator over a `Math.mod()`
> function? There is the precedent of the `**` operator implemented as
> alternative of `Math.pow()` few years ago. It would be interesting to hear
> the feedback of those that use regularly powers, whether the benefit was
> clear (personally, I almost never use either `Math.pow()` or `**`, so that
> I can’t say anything).
>
> At least one disadvantage of an operator over a function, is that you have
> to think about precedence. The problem is exacerbated in JS, because
> (following some other languages) the unary minus has an uncanny high
> precedence level, confusingly very different than the one of the binary
> minus; so that, after having designed `**`, it was realised at the last
> minute that `-a**b` would be dumbly interpreted as `(-a)**b` instead of
> `-(a**b)` or `0-a**b`, as anybody who would be likely to actually use the
> operator would expect. (That particular issue was resolved in a hurry by
> making the parenthesis-left form a syntax error.)
>
> —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: Re: Indexing HTML Attributes and Unique Indexes

2019-05-23 Thread Andrea Giammarchi
> while it could be considered a sub-set, JS is full of HTML related
features - `HTMLElement` for one.

HTMLElement is defined by the living DOM standard (WHATWG)
https://html.spec.whatwg.org/multipage/dom.html#htmlelement

it has nothing to do with JS.

JS is a general purpose programming language that implements ECMAScript
standard, which on the Web gets enriched with some functionality, while on
NodeJS it gets enriched with some other (and indeed HTMLELement doesn't
exist there).

In GJS (Dekstop UI) it has other features too, so asking in a JS related
mailing list to bring in something strictly DOM related (whatwg) is not
appropriate.

Historically speaking, the only thing that went in strictly DOM related
where things like String.prototype.blink methods and others, but today JS
is *really* not Web based anymore, even if Web is one of its primary goals
(but then again, with WASM around, any programming language can target the
Web, so you want this proposal to land in WHATWG, not here).

Regards



On Thu, May 23, 2019 at 7:15 PM Randy Buchholz 
wrote:

> @Andrea Giammarchi , While the connection is
> secondary, HTML often serves as the specification for the creation of JS
> objects. And while it could be considered a sub-set, JS is full of HTML
> related features - `HTMLElement` for one. Thing is, if you are programming
> in JS for browser applications, you’re dealing with HTML-adjacent JS at
> some point. What I’m trying to do, though, somewhat supports your point.  I
> see a lot of higher-level code manipulating HTML tags, which feels really
> wrong. Even dealing with `HTMLElement` in higher-level code doesn’t seem to
> make a lot of sense.  I’m trying to encapsulate the elements and tags, and
> move that point as far into the background as I can.
>
>
>
> @guest271314 
>
> If we think of Indexes as a type of key-value pairs, a “regular” Index
>  allows duplicate keys, and a Unique Index requires unique keys. Indexes
> are always sorted on their keys. So in this case, when the index is built,
> it creates k-v pairs of attributeName-elementId, ordered by attributeName.
> To get all elements with a specific attribute, we just find the first one
> with that key, and keep reading -`getElementbyId(elementId)` - until the
> key changes.
>
>
>
> You’re right about `id`. I’m converting generic, multi-instance template
> “tags” into  elements with id’s, so I can access them directly without
> searching. Just using `getElementById`. The template as been “localized”
> per instance, and encapsulated behind a controller. I want to avoid dealing
> with HTML, and even more HTTP verb related things like `Form` and
> `FormData` and just deal with general JS objects, so I use Models instead
> of things like `FormData`.
>
>
>
> So for example, the business perspective of a ”Person” has “Age” data. A
> page may display multiple people at once.
>
> ```
>
> 
>
> 
>
> ```
>
> The goal is to get from the source tag to non-html/element related JS as
> soon as possible.
>
>
>
> The template behind this might look something like
>
> ```
>
> 
>
>
>
> 
>
> 
>
> ```
>
>
>
> When `connectedCallback` runs, it creates  a `View` using the template
>
> ```
>
> 
>
>
>
>
>
> 
>
>
>
> 
>
> 
>
> 
>
> 
>
> ```
>
> A `Model`
>
> ```
>
> class person{
>
> name;
>
> age;
>
> }
>
>
>
> And a dynamically configured `Controller` and instance. A base Person
> class contains common functionality.
>
> ```
>
> class Person1 extends Person{
>
> get name(){ return document.getElementById(‘person1_name’)
>
> …
>
> get model(){ return this.populateModel();}
>
> }
>
> self.controllers.add(new Person1());
>
> ```
>
> Now I don’t need to deal with any HTML/element or “tag hierarchy” related
> JS. I pretty much abstract out the HTML and HTMLElement pieces when the
> Custom Element is initially loaded.
>
>
>
> ```
>
> const personAge = self.controllers.person1.age;
>
> ```
>
> At a lower level, I can create attribute related properties using the
> dynamically assigned element id.
>
>
>
> ```
>
> 
>
> ```
>
> This would end up creating a property or methods on the controller that
> allows me to not have to deal with styles and CSS classes directly, and
> even constrain values.
>
>
>
> ```
>
> self.controllers.person1.name.color = “red”;
>
> ```
>
>
>
> So the whole index thing started when I was loading/parsing dynamic
> html/JS code and searching for `prop` and `attrib` repeatedly. If I know
> I’m going to be searching on an attribute a lot, maybe I could give the
> parser/engine a hint it could use to optimize that search.
> ___
> 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: Indexing HTML Attributes and Unique Indexes

2019-05-23 Thread Andrea Giammarchi
it's meant there couldn't be two indexes with the same value, but even IDs
can be duplicated on a page (it's not suggested or anything, but nothing
prevents you to do that)

to be honest, since IDs already cover the whole story (IDs are accessible
even via globalThis/window, no need to query the document) I guess this
whole story is about having `el.uid`, as opposite of `el.id`, so that a
`uid` cannot be duplicated (it throws if it is), and
`document.uid[unique-uid-value]` would return, without querying, the live
node (if any)

however, I think this whole discussion in here makes no sense, as JS itself
has nothing to do with HTML 🤷‍♂️




On Thu, May 23, 2019 at 4:23 PM guest271314  wrote:

> If the HTML elements have a unique ```id``` set there is not search to
> perform (```document.getElementById("id")```), correct?
>
> Form fields can be created, set and changed using `FormData` objects
> without using HTML elements at all.
>
> Still not gathering what is meant by unique indexes.
>
> On Thu, May 23, 2019 at 2:05 PM Randy Buchholz 
> wrote:
>
>> Full Table Scans and Unique indexes are database concepts (that's the DBA
>> reference). When a database searches for a record based on a column value,
>> it might look at every record in the table to find the matches - scan the
>> entire (full) table, in the order the records were inserted or stored. To
>> speed this up, we can create indexes on table columns or column groups.
>> These are like ordered maps or hash tables. To find a record, more
>> efficient searches can be done against the indexes to find the records.
>> Indexes can also act as constraints. A "Unique Index" is a constraint that
>> checks a table to see if a value exists before inserting it in the table
>> and adding it to the index. Indexing has a trade-off. It slows inserting,
>> but improves searching. While understanding that databases and browsers are
>> worlds apart, a foundational part of database engines is searching, just
>> like it is in DOM manipulation. Indexing can provide orders of magnitude
>> performance improvements when reading/searchin
>>  g in databases. It seemed worth seeing if the concept translated across
>> technologies.
>>
>> Without any optimizations, an attribute search on a document would look
>> at each node, and then at each attribute of the node to find a match - Full
>> Table Scan. This makes searches very slow. At an absurd extreme, we could
>> index everything, making startup very slow and eating memory, but making
>> some searches very fast.  The balanced approach is to implement "indexing"
>> ourselves (using any of the mentioned approaches) to get the best level.
>>
>> About the code/HTML, it is dynamic and real-time. It is loaded over
>> WebSockets, and the elements are talking to the backend in real-time over
>> the sockets. I'm using an original (Trygve Reenskaug) MVC approach.
>> Essentially, each Web Component is an MVC component, with the HTML/elements
>> and code accessed only through the controller. I am looking at the incoming
>> code for cases where several searches ae being performed on the same
>> attribute (or element). I give these a generated `id`,  create indexes on
>> them, and expose them as properties on the controller. The underlying
>> framework uses a set of common attributes that are searched on a lot, but
>> only for a small set of elements. These are also indexed. So at the cost of
>> slower startup (offset to some degree by doing some of this in a Web Worker
>> and/or server-side), I can read and write "Form Fields" quickly.
>>
>> Many language features are implemented to wrap or optimize common or
>> repetitive use cases, or to move code to a more efficient part of the
>> architecture. Indexing can do both. Without doing things server-side or in
>> Workers, the indexing consumes UI cycles. Adding an indexing "hint" could
>> allow all or part of this code to be moved back into the "system" or C++
>> layer. (e.g., into `querySelect` internals supported by low-level map
>> stores) Or to parsing (like I'm doing), taking some of the repetitive work
>> off the UI and developers hands.
>>
>> ___
>> 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: Indexing HTML Attributes and Unique Indexes

2019-05-22 Thread Andrea Giammarchi
live *

On Wed, May 22, 2019 at 7:25 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> With Custom Elements you have `attributeChangedCallback` which reacts
> after `observedAttributes` returned attributes, and I believe you'd like to
> use that to create getters and setters out of the box.
>
> I don't think DOM specific class fields/syntax will ever land in JS
> itself, but I can suggest you looking at most handy custom elements
> patterns in here:
> https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4
>
> About being unique, you can always `document.querySelector('[attribute="'
> + value +'"]')` and, if not null, throw an error 'cause already live on the
> DOM.
>
> However, IDs are the most "unique" thing you can have, even if 2 IDs with
> same content are still allowed love on the document.
>
> If you look for an easy way to have unique IDs, remember you can start
> from `let id = Math.random()` and do `++id` any other time to have a new,
> rarely clashing, unique name. Prefix it with the `nodeName` and see you've
> already all uniqueness you need for you custom elements, since you can't
> define two custom elements with the same name anyway (yet, unless scoped,
> but that's another story).
>
> Regards
>
> On Wed, May 22, 2019 at 7:07 PM Randy Buchholz 
> wrote:
>
>> I’ve been working with `Custom Elements` and I’m writing a lot of code
>> against tag attributes. In some cases, I want the attribute values to be
>> unique on a page (like `id`).  It got me wondering about how the engines
>> handle attribute based searches, and if indexing (with unique/distinct
>> options) would provide value. I also find myself writing a lot of
>> boilerplate getters/setters for attributes in the elements. Attribute
>> handling could be improved by adding some additional support with something
>> like an `attrib` feature. This would be similar to `get` or `set` in use.
>>
>>
>>
>> ```
>>
>> class MyElement extends HTMLElement{
>>
>> attrib myAttrib(‘my-attribute’) index distinct;
>>
>> }
>>
>> ```
>>
>> This would create the attribute `my-attribute` on the tag and element,
>> and also generate a getter and setter
>>
>> ```
>>
>> get myAttrib() { return this.getAttribute(‘my-attribute’); }
>>
>> set myAttrib(v) { this.setAttribute(‘my-attribute’, v); }
>>
>> ```
>>
>> The `index` flag it would tell the engine it should create a map/hash to
>> improve search optimization for heavily searched attributes.
>>
>> The `distinct` flag would indicate that all values for that attribute
>> within context (e.g., document) should be unique. This might be used
>> primarily by IDE’s to generate warnings.
>> ___
>> 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: Indexing HTML Attributes and Unique Indexes

2019-05-22 Thread Andrea Giammarchi
With Custom Elements you have `attributeChangedCallback` which reacts after
`observedAttributes` returned attributes, and I believe you'd like to use
that to create getters and setters out of the box.

I don't think DOM specific class fields/syntax will ever land in JS itself,
but I can suggest you looking at most handy custom elements patterns in
here:
https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4

About being unique, you can always `document.querySelector('[attribute="' +
value +'"]')` and, if not null, throw an error 'cause already live on the
DOM.

However, IDs are the most "unique" thing you can have, even if 2 IDs with
same content are still allowed love on the document.

If you look for an easy way to have unique IDs, remember you can start from
`let id = Math.random()` and do `++id` any other time to have a new, rarely
clashing, unique name. Prefix it with the `nodeName` and see you've already
all uniqueness you need for you custom elements, since you can't define two
custom elements with the same name anyway (yet, unless scoped, but that's
another story).

Regards

On Wed, May 22, 2019 at 7:07 PM Randy Buchholz 
wrote:

> I’ve been working with `Custom Elements` and I’m writing a lot of code
> against tag attributes. In some cases, I want the attribute values to be
> unique on a page (like `id`).  It got me wondering about how the engines
> handle attribute based searches, and if indexing (with unique/distinct
> options) would provide value. I also find myself writing a lot of
> boilerplate getters/setters for attributes in the elements. Attribute
> handling could be improved by adding some additional support with something
> like an `attrib` feature. This would be similar to `get` or `set` in use.
>
>
>
> ```
>
> class MyElement extends HTMLElement{
>
> attrib myAttrib(‘my-attribute’) index distinct;
>
> }
>
> ```
>
> This would create the attribute `my-attribute` on the tag and element, and
> also generate a getter and setter
>
> ```
>
> get myAttrib() { return this.getAttribute(‘my-attribute’); }
>
> set myAttrib(v) { this.setAttribute(‘my-attribute’, v); }
>
> ```
>
> The `index` flag it would tell the engine it should create a map/hash to
> improve search optimization for heavily searched attributes.
>
> The `distinct` flag would indicate that all values for that attribute
> within context (e.g., document) should be unique. This might be used
> primarily by IDE’s to generate warnings.
> ___
> 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: Proposal: native XML object support.

2019-05-21 Thread Andrea Giammarchi
People use JSX, which is basically E4X, so I'd argue the word useless is
not really appropriate. You can use E4X to produce HTML, the fact we're
talking XML is merely about the E4X background, but as you could produce
strings out of E4X you could do the same and have better templating out of
the box.

But like I've said, I already use template literal tags, but those strings
don't get hints or highlights as if these were E4X, XML, or plain HTML,
which is the only cool thing I'd personally find useful.

Maybe it's just a tooling issue though.

On Mon, May 20, 2019 at 3:06 PM ViliusCreator 
wrote:

> > the client, it could still somehow shine in NodeJS though.
>
>
>
> The only way it can shine is only passing HTML objects as arg to website.
> That’s it. And still, you can use string to do that for you. People already
> use JSON and I don’t think they would use XML in Node js. There are already
> tons of libs for XML stuff, yet they don’t have a lot of downloads, as far
> as I remember.
>
>
>
> So basically, Node js doesn’t need XML. That would be useless.
> ___
> 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: Proposal: native XML object support.

2019-05-20 Thread Andrea Giammarchi
That'd give you info after declaration, which I believe was the major
concern in using strings instead of literals.

FWIW, I also wish E4X was still a thing, despite these handy and successful
template literals based libraries (hyperHTML, lighterhtml, or heresy for
the client, viperHTML for NodeJS).

However, since `() => ` is always new node while `() => html``` is a unique literal, I think E4X would be a performance nightmare on
the client, it could still smehow shine in NodeJS though.

Regards

On Mon, May 20, 2019 at 2:03 PM ViliusCreator 
wrote:

> > With strings and even E4X, you don't get the same experience that react
> supports. Things like property completion in XML mode, XML internal logic,
> etc.
>
>
>
> Pretty sure you can do this:
>
>
>
> ```js
> // ... xml function definition
>
> /**
>
> * @type {Element}
>
> * @prop {string} href
>
> */
> const xmlObj = xml`something`
>
> ```
>
>
> This should make editor auto-complete xml object for you.
> ___
> 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: Actual WeakSet Use Cases

2019-04-23 Thread Andrea Giammarchi
wickedElements
<https://github.com/WebReflection/wicked-elements#wickedelements> is one
example:

   1. you register CSS selectors used through MutationObserver, so that
   connected nodes are passed to the 'connected' listener
   2. you setup nodes in such listener only if these were not already setup
   3. any other disconnect/connect event won't bother nodes setup, if these
   already handled

The disconnected
<https://github.com/WebReflection/disconnected#disconnected> utility (used
in hyperHTML and lighterhtml): if the node part of the group that has been
connected or disconnected was observed, meaning that the WeakSet knew it
already, then the event triggers, otherwise nothing happens.

In both cases the pattern is pretty similar:

const observed = new WeakSet;
const observe = node => {
  observed.add(node);
};
const magic = event => {
  console.log('magic', event.currentTarget);
};
const addMagicIfObserved = node => {
  if (observed.has(node))
node.addListener('magic', magic);
  for (const child of node.children)
addMagicIfObserved(child);
};
new MutationObserver(mutations => {
  for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
  addMagicIfObserved(node);
}
  }
}).observe(document, {childList: true, subtree: true});

The list of pros is pretty simple too:

   1. with modules scoped utilities, you don't leak undesired details
   2. you don't need to cleanup after or change state *unless* you provide
   a way to stop observing

Regards


On Tue, Apr 23, 2019 at 9:27 PM Scott Rudiger 
wrote:

> Would anyone mind sharing some examples of the use cases Andrea and Andy
> mentioned?
>
> On Tue, Apr 23, 2019 at 6:32 AM Michał Wadas 
> wrote:
>
>> You can't do "branding" by properties on frozen objects.
>>
>> On Tue, 23 Apr 2019, 13:44 Andy Earnshaw,  wrote:
>>
>>> This is pretty much what I used it for in a previous job role. We loaded
>>> and unloaded various iframes, registering APIs and custom elements inside
>>> them, adding the `window` object to a WeakSet so the initialisation only
>>> ran once.
>>>
>>> On Tue, 23 Apr 2019 at 10:26, Andrea Giammarchi <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> WeakSet can be very useful in general to avoid *any* object to be
>>>> visited/setup twice, not just those coming from user-land classes.
>>>>
>>>> Circular references, mixins, DOM nodes one-off events handling, and so
>>>> on and so fort.
>>>>
>>>> On Mon, Apr 22, 2019 at 8:26 PM #!/JoePea  wrote:
>>>>
>>>>> (I edited the broken format of my previous post)
>>>>>
>>>>> What other use cases are there?
>>>>>
>>>>> On Mon, Apr 22, 2019 at 11:20 AM #!/JoePea  wrote:
>>>>>
>>>>>> > WeakSets are perfect for branding and are how I would expect web
>>>>>> platform class branding to be explained.
>>>>>> >
>>>>>> > ```js
>>>>>> > const foos = new WeakSet();
>>>>>> >
>>>>>> > class Foo {
>>>>>> >   constructor() {
>>>>>> > foos.add(this);
>>>>>> >   }
>>>>>> >
>>>>>> >   method() {
>>>>>> > if (!foos.has(this)) {
>>>>>> >   throw new TypeError("Foo.prototype.method called on an
>>>>>> incompatible object!");
>>>>>> > }
>>>>>> >   }
>>>>>> > }
>>>>>> > ```
>>>>>>
>>>>>> Just curious, is that effectively the same as what the (current)
>>>>>> [private fields proposal](
>>>>>> https://github.com/tc39/proposal-class-fields) offers?
>>>>>>
>>>>>> ```js
>>>>>> class Foo {
>>>>>>   #isFoo = true
>>>>>>
>>>>>>   method() {
>>>>>> if (this.#isFoo) {
>>>>>>   throw new TypeError("Foo.prototype.method called on an
>>>>>> incompatible object!");
>>>>>> }
>>>>>>   }
>>>>>> }
>>>>>> ```
>>>>>>
>>>>>> - Joe
>>>>>>
>>>>> ___
>>>>> 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
>>>
>> ___
>> 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: Re: Actual WeakSet Use Cases

2019-04-23 Thread Andrea Giammarchi
WeakSet can be very useful in general to avoid *any* object to be
visited/setup twice, not just those coming from user-land classes.

Circular references, mixins, DOM nodes one-off events handling, and so on
and so fort.

On Mon, Apr 22, 2019 at 8:26 PM #!/JoePea  wrote:

> (I edited the broken format of my previous post)
>
> What other use cases are there?
>
> On Mon, Apr 22, 2019 at 11:20 AM #!/JoePea  wrote:
>
>> > WeakSets are perfect for branding and are how I would expect web
>> platform class branding to be explained.
>> >
>> > ```js
>> > const foos = new WeakSet();
>> >
>> > class Foo {
>> >   constructor() {
>> > foos.add(this);
>> >   }
>> >
>> >   method() {
>> > if (!foos.has(this)) {
>> >   throw new TypeError("Foo.prototype.method called on an
>> incompatible object!");
>> > }
>> >   }
>> > }
>> > ```
>>
>> Just curious, is that effectively the same as what the (current) [private
>> fields proposal](https://github.com/tc39/proposal-class-fields) offers?
>>
>> ```js
>> class Foo {
>>   #isFoo = true
>>
>>   method() {
>> if (this.#isFoo) {
>>   throw new TypeError("Foo.prototype.method called on an incompatible
>> object!");
>> }
>>   }
>> }
>> ```
>>
>> - Joe
>>
> ___
> 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: Static Typing

2019-04-05 Thread Andrea Giammarchi
we could add a `Typed` primitive every typed value inherits from, similar
way every object implicitly inherits from `Object` these days.

That, by contract, would disallow any prototype related operation to either
classes or instances, and it will simplify the `Reflect.isTyped(thing)`
algo.

class MyType extends Typed {}
const num:i32 = 123;

the `MyType` class, and every instance of it, cannot have mutated
prototype, and so cannot the `num`.

Typed values will be all shortcuts that behave like a Typed instance.

That should solves all cases, right?





On Thu, Apr 4, 2019 at 8:52 PM Ranando King  wrote:

> >  if we base any assumption only to the current highly dynamic nature of
> JS we won't go too far.
>
> Problem is that if we infringe on the "current highly dynamic nature of
> JS", we'll end up breaking valuable use cases. Any new feature added should
> always be 100% compatible with the non-competing portions of the existing
> language.
>
> > I think the mutable prototype issue can be solved through static classes
> where no changes would be possible and all instances would be immune to
> `setPrototypeOf`
>
> That solves half of the problem. What of the other half (`Type v =
> "somevalue";` where `Type` is not a static class)? With your approach, that
> would need to be restricted to solve the other half. Otherwise, you'd still
> be facing the issues Waldemar spoke about.
>
> On Thu, Apr 4, 2019 at 2:49 AM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> If something is missing, let's move forward finding out solutions, 'cause
>> if we base any assumption only to the current highly dynamic nature of JS
>> we won't go too far.
>>
>> As example, I think the mutable prototype issue can be solved through
>> static classes where no changes would be possible and all instances would
>> be immune to `setPrototypeOf`
>>
>> ```
>> static class MyType {}
>>
>> Reflect.setPrototypeOf(MyType, Array); // nope
>> Reflect.setPrototypeOf(new MyType, []); // nope
>> ```
>>
>> we'll also need a `Reflect.isTyped(ref)` in case we'd like to throw
>> errors on prototype set attempts.
>>
>>
>>
>> On Thu, Apr 4, 2019 at 6:11 AM Ranando King  wrote:
>>
>>> > - If you allow user-defined types, objects can spontaneously change
>>> their type by mutating their prototype.  Thus, you can declare a variable x
>>> to have type Foo and check that you're assigning an instance of Foo to it,
>>> but the value x can become a Bar (different from a Foo) spontaneously
>>> without any operations on x.
>>>
>>> At least for static typing, the engine will need to freeze a copy of the
>>> class definition at the time when the static type is referenced. That
>>> frozen type will be associated with the variable in a fixed way, making all
>>> attempts to change the type of the variable fail. Also, that would need to
>>> divorce the frozen type from the dynamic version so the dynamic version can
>>> still be mutated. That concept should work, but it might prove to be
>>> ridiculously complicated since it risks a proliferation of objects all of
>>> type Foo but with different type definitions. One way to get around that is
>>> to flag a type as static the first time it is used in a statically typed
>>> variable definition. This would cause an error to be thrown should any part
>>> of the class be altered. Not sure how workable that is.
>>>
>>> > but that begs the question of what is the type of just ['a', 'b'].
>>>
>>> It should be any[]. Typing should be as non-aggressive as possible. Auto
>>> typing should only consider the top level data to determine the type, and
>>> in this case, that's an Array. To make c restricted to string elements, the
>>> type would need to be specified as string[].
>>>
>>> > If you follow this to its logical conclusion and think about what the
>>> types of various methods that work on arrays should be, you end up with an
>>> enormous and confusing variety of array and object types, which is
>>> something we explored years ago.
>>>
>>> Maybe, but that's always the case with any type system that allows for
>>> user-defined types. The main problem here is the memory requirements for
>>> storing all of those types. If I remember the description of V8 internals,
>>> it seems to have already managed this issue. At least in V8, the challenge
>>> would be in permanently associating a specific evolution 

Re: Proposal: Static Typing

2019-04-04 Thread Andrea Giammarchi
If something is missing, let's move forward finding out solutions, 'cause
if we base any assumption only to the current highly dynamic nature of JS
we won't go too far.

As example, I think the mutable prototype issue can be solved through
static classes where no changes would be possible and all instances would
be immune to `setPrototypeOf`

```
static class MyType {}

Reflect.setPrototypeOf(MyType, Array); // nope
Reflect.setPrototypeOf(new MyType, []); // nope
```

we'll also need a `Reflect.isTyped(ref)` in case we'd like to throw errors
on prototype set attempts.



On Thu, Apr 4, 2019 at 6:11 AM Ranando King  wrote:

> > - If you allow user-defined types, objects can spontaneously change
> their type by mutating their prototype.  Thus, you can declare a variable x
> to have type Foo and check that you're assigning an instance of Foo to it,
> but the value x can become a Bar (different from a Foo) spontaneously
> without any operations on x.
>
> At least for static typing, the engine will need to freeze a copy of the
> class definition at the time when the static type is referenced. That
> frozen type will be associated with the variable in a fixed way, making all
> attempts to change the type of the variable fail. Also, that would need to
> divorce the frozen type from the dynamic version so the dynamic version can
> still be mutated. That concept should work, but it might prove to be
> ridiculously complicated since it risks a proliferation of objects all of
> type Foo but with different type definitions. One way to get around that is
> to flag a type as static the first time it is used in a statically typed
> variable definition. This would cause an error to be thrown should any part
> of the class be altered. Not sure how workable that is.
>
> > but that begs the question of what is the type of just ['a', 'b'].
>
> It should be any[]. Typing should be as non-aggressive as possible. Auto
> typing should only consider the top level data to determine the type, and
> in this case, that's an Array. To make c restricted to string elements, the
> type would need to be specified as string[].
>
> > If you follow this to its logical conclusion and think about what the
> types of various methods that work on arrays should be, you end up with an
> enormous and confusing variety of array and object types, which is
> something we explored years ago.
>
> Maybe, but that's always the case with any type system that allows for
> user-defined types. The main problem here is the memory requirements for
> storing all of those types. If I remember the description of V8 internals,
> it seems to have already managed this issue. At least in V8, the challenge
> would be in permanently associating a specific evolution of an internal
> type to a variable.
>
> On Wed, Apr 3, 2019 at 7:50 PM Waldemar Horwat 
> wrote:
>
>> On 3/23/19 1:34 PM, IdkGoodName Vilius wrote:
>> > This is a proposal for static typing. Here is the github repository
>> link: https://github.com/CreatorVilius/Proposal-Static-Typing
>> > I think it would be great thing in JS.
>>
>> We intentionally reserved syntax so that something like that would be
>> possible in the future.
>>
>> I've also spent a lot of time working on past proposals to do such
>> things.  A few interesting issues would invariably arise that make both
>> static and runtime typing unsound:
>>
>> - If you allow user-defined types, objects can spontaneously change their
>> type by mutating their prototype.  Thus, you can declare a variable x to
>> have type Foo and check that you're assigning an instance of Foo to it, but
>> the value x can become a Bar (different from a Foo) spontaneously without
>> any operations on x.
>>
>> - Something similar happens with trying to type arrays.  You wrote:
>>
>> let c: auto = ['a', 'b']  // c is now string[]
>>
>> but that begs the question of what is the type of just ['a', 'b'].
>>
>> - Is it string[]?  No, it can't be that because you can replace its
>> second element with a number.
>> - Is it any[]?  Well, in that case c should have type any[], not string[]
>> - Is it object?  In that case c should have type Object.
>> and so on.
>>
>> If you follow this to its logical conclusion and think about what the
>> types of various methods that work on arrays should be, you end up with an
>> enormous and confusing variety of array and object types, which is
>> something we explored years ago.  In some cases you'd want structural
>> types, in some cases you'd want 'like' types (an array of anything which
>> just happens to hold numbers at the moment), and so on.
>>
>>  Waldemar
>> ___
>> 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-dis

Re: Proposal: Static Typing

2019-03-26 Thread Andrea Giammarchi
Actually, on that very same note, since WASM <-> JS might be the only
reason, or likely the best one, to have types in JS, let's consider from
scratch all WASM types as possible primitives to adopt, shall we?

i32 (alias as int?)
i64
f32 (alias as float?)
f64
u32 (alias uint?)

then we have functype (function) limits (dynamic arrays) memory (static
arrays) and tables (objects/maps) to deal with, plus global and external.

If we find a syntax to represent these types, targeting, or consuming in an
optimized way, WASM, might be a reality, with better results than asm.js,
since that's very hard to write / remember for humans, IMO.

I also would like to know the opinion of someone close to V8 or other
engines.

Regards







On Tue, Mar 26, 2019 at 10:03 AM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> jsdoc doesn't exist in production so it cannot provide any info to the
> runtime, making WASM interoperability and hot code optimizations impossible.
>
> Let's please keep the discussion focused on the achievements current JS
> cannot possibly have, thanks.
>
>
>
> On Tue, Mar 26, 2019 at 9:06 AM Dan Peddle  wrote:
>
>> It's really a shame few mention jsdoc anymore. It provides mechanisms to
>> achieve all of these developer experience quality of life improvements
>> without needing transpiling, and on top of standard js of various flavours,
>> progressively.
>>
>>
>> On 26. Mar 2019, at 06:43, Ranando King  wrote:
>>
>> Doesn't V8 already use such a concept to manage optimization? When a
>> reference's structure mutates, V8 generates a new type by extending the
>> previous one with the changes, then kills any affected optimizations around
>> the mutated object, forcing re-optimization. Static types would essentially
>> provide a guarantee that such re-optimizations would be completely
>> unnecessary for the lifetime of the object since it would be impossible to
>> mutate the object's structure. It would also allow for early optimization
>> since the structure would already be known. These are the benefits of
>> static typing. It's not just a matter of developer trust but also engine
>> efficiency.
>>
>> On Tue, Mar 26, 2019 at 12:21 AM Randy Buchholz 
>> wrote:
>>
>>> I recently started doing a lot of ES, coming from C# and really missed
>>> “typings” at first. But once I learned to think more in es,  they became
>>> less necessary – even cumbersome in some ways. The question for me on this
>>> really comes down to what is a ”type” and what value does it bring. As I
>>> see it, a type is a structural contract, in the same way an interface is a
>>> behavioral contract. The value of contracts is that they minimize the need
>>> to trust. I.e., if I pass a known-type to a function, I can know that it
>>> will have a specific structure (e.g., known properties and methods in a
>>> class).  Without types, I must trust or check the structure. But, types
>>> aren’t really self-aware. It is the environment that enforces types. Once
>>> you have types, you must have what I call a “Type Authority”. Built-in
>>> types are always known by the authority, and when you declare a type,  you
>>> are adding to what the authority knows. The authority can look at the code
>>> and do the “checking” of what is passed based on what it knows. Having
>>> types lets me not have to trust in what I am receiving – it can be verified
>>> for me.
>>>
>>>
>>>
>>> In a compiled language, types provide “hidden” value. The compiler can
>>> look at the entire code based and make optimization decisions around types
>>> (e.g., in-lining). In a dynamic, interpreted language, (for the most part)
>>> this doesn’t happen. Types must be processed at each point of use. So, the
>>> value of types stays mostly limited to knowing the structure. Which is
>>> though, extremely useful. The problem with static types, is that they exist
>>> at the wrong place in time. A static type is a design-time constraint. Yet
>>> the environment doesn’t really know about the type until each run-time use.
>>> This puts unnecessary limits on the language – adding a property at
>>> run-time (while scary at first) is one of my favorite features of the
>>> language. Static typing adds other layers of complexity – like namespaces.
>>> Locking down a type at design-time essentially “hijacks” a name. A static
>>> type “Person” must be consistent across the entire application environment.
>>> In uses like Web, where it is common to pull code from many remote sour

Re: Proposal: Static Typing

2019-03-26 Thread Andrea Giammarchi
jsdoc doesn't exist in production so it cannot provide any info to the
runtime, making WASM interoperability and hot code optimizations impossible.

Let's please keep the discussion focused on the achievements current JS
cannot possibly have, thanks.



On Tue, Mar 26, 2019 at 9:06 AM Dan Peddle  wrote:

> It's really a shame few mention jsdoc anymore. It provides mechanisms to
> achieve all of these developer experience quality of life improvements
> without needing transpiling, and on top of standard js of various flavours,
> progressively.
>
>
> On 26. Mar 2019, at 06:43, Ranando King  wrote:
>
> Doesn't V8 already use such a concept to manage optimization? When a
> reference's structure mutates, V8 generates a new type by extending the
> previous one with the changes, then kills any affected optimizations around
> the mutated object, forcing re-optimization. Static types would essentially
> provide a guarantee that such re-optimizations would be completely
> unnecessary for the lifetime of the object since it would be impossible to
> mutate the object's structure. It would also allow for early optimization
> since the structure would already be known. These are the benefits of
> static typing. It's not just a matter of developer trust but also engine
> efficiency.
>
> On Tue, Mar 26, 2019 at 12:21 AM Randy Buchholz 
> wrote:
>
>> I recently started doing a lot of ES, coming from C# and really missed
>> “typings” at first. But once I learned to think more in es,  they became
>> less necessary – even cumbersome in some ways. The question for me on this
>> really comes down to what is a ”type” and what value does it bring. As I
>> see it, a type is a structural contract, in the same way an interface is a
>> behavioral contract. The value of contracts is that they minimize the need
>> to trust. I.e., if I pass a known-type to a function, I can know that it
>> will have a specific structure (e.g., known properties and methods in a
>> class).  Without types, I must trust or check the structure. But, types
>> aren’t really self-aware. It is the environment that enforces types. Once
>> you have types, you must have what I call a “Type Authority”. Built-in
>> types are always known by the authority, and when you declare a type,  you
>> are adding to what the authority knows. The authority can look at the code
>> and do the “checking” of what is passed based on what it knows. Having
>> types lets me not have to trust in what I am receiving – it can be verified
>> for me.
>>
>>
>>
>> In a compiled language, types provide “hidden” value. The compiler can
>> look at the entire code based and make optimization decisions around types
>> (e.g., in-lining). In a dynamic, interpreted language, (for the most part)
>> this doesn’t happen. Types must be processed at each point of use. So, the
>> value of types stays mostly limited to knowing the structure. Which is
>> though, extremely useful. The problem with static types, is that they exist
>> at the wrong place in time. A static type is a design-time constraint. Yet
>> the environment doesn’t really know about the type until each run-time use.
>> This puts unnecessary limits on the language – adding a property at
>> run-time (while scary at first) is one of my favorite features of the
>> language. Static typing adds other layers of complexity – like namespaces.
>> Locking down a type at design-time essentially “hijacks” a name. A static
>> type “Person” must be consistent across the entire application environment.
>> In uses like Web, where it is common to pull code from many remote sources
>> and libraries,  how does “Person” remain “static” across these?
>>
>>
>>
>> I would propose an alternative to static typing – the Type Authority. The
>> Type Authority is a architecture component that (among other things)
>> provides “scoped/run-time statics”. Essentially, the Type Authority is an
>> application-wide dynamic repository of types, in the run-time environment.
>> This opt-in feature would allow dynamically creating types, and then making
>> them “fixed” them with application scope. Once registered, the type is
>> basically static. Using a hierarchal approach and “dotted” naming notation,
>> (e.g., library.component.typename) types can be localized or extended. For
>> example, a library can be imported, and types given a “namespace prefix”.
>> The qualified name would effectively be a static type within the
>> application context. Properties could be dynamically added, and the new
>> type registered as a ”child type” (e.g., Person => Person.Domain). This
>> would then allow casting - (Person)DomainPersonInstance. A simple Type
>> Authority would support basic “is a”/”typeof” capabilities. A more advanced
>> system could provide factory methods.
>>
>>
>>
>> This approach provides a way to enforce the structural contract nature of
>> types, while retaining the dynamic nature of the language.
>> ___
>> es-discuss mailing list
>

Re: Proposal: Static Typing

2019-03-25 Thread Andrea Giammarchi
* trough (gz)

On Mon, Mar 25, 2019 at 11:41 AM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> > WASM interoperability and optimiser efficiency instead of developer
> productivity.
>
> I've personally always seen types useful **only** for typed languages
> interoperability and/or optimization/performance hints to engines/runtimes,
> but since many developers apparently experience some productivity boost
> though typed languages oriented tools, why not having all the three checked?
>
>- WASM interoperability (a TC39 effort)
>- more efficient runtime (a runtime/engine effort)
>- boosted productivity (a third parts tools effort)
>
> That doesn't look too bad to me, as possible JS' future.
>
> Regards
>
>
> On Mon, Mar 25, 2019 at 11:19 AM Bergi  wrote:
>
>> Hi,
>>
>> > I am having hard time understanding the counter argument "you need a
>> > transpiler anyway".
>>
>> Sorry, I agree it's a bad argument, I should have just omitted it.
>> It was meant to support "If you are only looking for development-time
>> benefits, you have to install a static toolchain anyway - which might as
>> well transpile away the annotations".
>>
>> >> the real value of strict types, in my view, is at development time,
>> > not at run time.
>> >
>> > This is not correct. Check what AssemblyScript managed to do via types,
>> > targeting WASM instead of non-typed JS
>> >
>> >> I would be curious to know if anybody has a usage for them at run time
>> >
>> > Developers might not have such usage, but V8 / Chakra / JSC /
>> > SpiderMonkey might spin up optimizations ahead of time, enabling right
>> > away hot code.
>>
>> ...or at least allow throwing exceptions instead of having to
>> de-optimise a JITted code, which allows simpler & better optimisation
>> algorithms.
>>
>> These are the kinds of arguments I want to hear, reasons for sending
>> type annotations to the client/runtime. And such a goal puts a very
>> different focus on what the type system should look like: WASM
>> interoperability and optimiser efficiency instead of developer
>> productivity.
>>
>> kind regards,
>>   Bergi
>> ___
>> 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: Static Typing

2019-03-25 Thread Andrea Giammarchi
> WASM interoperability and optimiser efficiency instead of developer
productivity.

I've personally always seen types useful **only** for typed languages
interoperability and/or optimization/performance hints to engines/runtimes,
but since many developers apparently experience some productivity boost
though typed languages oriented tools, why not having all the three checked?

   - WASM interoperability (a TC39 effort)
   - more efficient runtime (a runtime/engine effort)
   - boosted productivity (a third parts tools effort)

That doesn't look too bad to me, as possible JS' future.

Regards


On Mon, Mar 25, 2019 at 11:19 AM Bergi  wrote:

> Hi,
>
> > I am having hard time understanding the counter argument "you need a
> > transpiler anyway".
>
> Sorry, I agree it's a bad argument, I should have just omitted it.
> It was meant to support "If you are only looking for development-time
> benefits, you have to install a static toolchain anyway - which might as
> well transpile away the annotations".
>
> >> the real value of strict types, in my view, is at development time,
> > not at run time.
> >
> > This is not correct. Check what AssemblyScript managed to do via types,
> > targeting WASM instead of non-typed JS
> >
> >> I would be curious to know if anybody has a usage for them at run time
> >
> > Developers might not have such usage, but V8 / Chakra / JSC /
> > SpiderMonkey might spin up optimizations ahead of time, enabling right
> > away hot code.
>
> ...or at least allow throwing exceptions instead of having to
> de-optimise a JITted code, which allows simpler & better optimisation
> algorithms.
>
> These are the kinds of arguments I want to hear, reasons for sending
> type annotations to the client/runtime. And such a goal puts a very
> different focus on what the type system should look like: WASM
> interoperability and optimiser efficiency instead of developer
> productivity.
>
> kind regards,
>   Bergi
> ___
> 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: Static Typing

2019-03-25 Thread Andrea Giammarchi
the day I'll disable autocorrect everywhere will be always too late ...

transpolar => transpilers
trample => transpile





On Mon, Mar 25, 2019 at 10:13 AM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> I am having hard time understanding the counter argument "you need a
> transpolar anyway".
>
> That's been the case since ES2015 landed with breaking syntax that has
> been required mandatory transpilation to keep it backward compatible, with
> things also not really transpilble such as classes with built-in extends
> ability.
>
> Why suddenly the "need to transpile" is considered a point against any new
> JS feature? Are we already done with JS, if that's the case?
>
> TypeScript exists and it has its own problems, 'cause its slightly
> diversions from what's defined via TC39 causes just confusion (i.e. private
> fields, to name one, built-in extends still broken if you target ES5, while
> Babel 7 fixed that, and template literals behave differently too - Babel 7
> is the only one producing a standard behavior)
>
> On top of that, many things recently landed in JS has been inspired by
> CoffeeScript ... where was the "just use CoffeeScript" argument at that
> time? Transpilers were already a thing then too.
>
> Moreover ...
>
> > the real value of strict types, in my view, is at development time, not
> at run time.
>
> This is not correct. Check what AssemblyScript managed to do via types,
> targeting WASM instead of non-typed JS
>
> If TypeScript, with its quirks, will be the language that help developers
> and win JS in the WASM field, we can start considering JS a second class
> citizen of the Web (and soon of the backend too, see deno).
>
> Is this where we are with JS?
>
> > I would be curious to know if anybody has a usage for them at run time
>
> Developers might not have such usage, but V8 / Chackra / JSC /
> SpiderMonkey might spin up optimizations ahead of time, enabling right away
> hot code.
>
> > a "toolchain" that allows strict typing using JavaScript without having
> to "use TypeScript".
>
> even if it'll end up being identical or redundant, but I doubt it, for
> many companies/teams the least third parts dependencies you have the better
> is for code reliability.
>
> I personally don't trust TS because it breaks when it targets ES5 and I
> cannot control what other people target, but I would trust the standard
> path and tools aiming at all cost to trample it right, whenever transpiring
> is needed.
>
> With Edge moving to use Chrome, and Firefox and WebKit always catching up,
> these days introducing anything new might need transpilers just for a
> couple of years, instead of decades.
>
> Best Regards
>
>
>
>
>
> On Mon, Mar 25, 2019 at 9:55 AM Naveen Chawla 
> wrote:
>
>> Yes the real value of strict types, in my view, is at development time,
>> not at run time.
>>
>> However I would be curious to know if anybody has a usage for them at run
>> time, and an example of such a case...
>>
>> Otherwise, yes a "toolchain" that allows strict typing using JavaScript
>> without having to "use TypeScript".
>>
>> On Mon, 25 Mar 2019 at 04:58, Ranando King  wrote:
>>
>>> One thing is definitively true. Any static type system added to ES must
>>> not be mandatory. Untyped code must be able to call typed code without
>>> forcing references into a fixed type. Likewise, typed code must be able to
>>> call untyped code without forcing references to give up type guarantees.
>>>
>>> On Sun, Mar 24, 2019 at 8:48 PM kai zhu  wrote:
>>>
>>>> i share a similar concern that static-typing makes little sense in
>>>> high-churn-rate UX-workflow-programming.
>>>>
>>>> it encourage people to bikeshed for correctness, on low-level code that
>>>> frequently gets rewritten every few weeks/months -- and with often
>>>> demoralizing effects.
>>>>
>>>> > On 24 Mar 2019, at 17:26, Bergi  wrote:
>>>> >
>>>> > Hello,
>>>> > to play the devils advocate: why does JavaScript need static typing?
>>>> >
>>>> > Your proposal doesn't really answer that. Sure, it mentions tooling
>>>> and
>>>> > IDEs that can provide you with type hints and complain on mistakes,
>>>> but
>>>> > things like Flow and Typescript do this today already.
>>>> > What's your goal, to have JS engines run Typescript(-like) code
>>>> natively

Re: Proposal: Static Typing

2019-03-25 Thread Andrea Giammarchi
I am having hard time understanding the counter argument "you need a
transpolar anyway".

That's been the case since ES2015 landed with breaking syntax that has been
required mandatory transpilation to keep it backward compatible, with
things also not really transpilble such as classes with built-in extends
ability.

Why suddenly the "need to transpile" is considered a point against any new
JS feature? Are we already done with JS, if that's the case?

TypeScript exists and it has its own problems, 'cause its slightly
diversions from what's defined via TC39 causes just confusion (i.e. private
fields, to name one, built-in extends still broken if you target ES5, while
Babel 7 fixed that, and template literals behave differently too - Babel 7
is the only one producing a standard behavior)

On top of that, many things recently landed in JS has been inspired by
CoffeeScript ... where was the "just use CoffeeScript" argument at that
time? Transpilers were already a thing then too.

Moreover ...

> the real value of strict types, in my view, is at development time, not
at run time.

This is not correct. Check what AssemblyScript managed to do via types,
targeting WASM instead of non-typed JS

If TypeScript, with its quirks, will be the language that help developers
and win JS in the WASM field, we can start considering JS a second class
citizen of the Web (and soon of the backend too, see deno).

Is this where we are with JS?

> I would be curious to know if anybody has a usage for them at run time

Developers might not have such usage, but V8 / Chackra / JSC / SpiderMonkey
might spin up optimizations ahead of time, enabling right away hot code.

> a "toolchain" that allows strict typing using JavaScript without having
to "use TypeScript".

even if it'll end up being identical or redundant, but I doubt it, for many
companies/teams the least third parts dependencies you have the better is
for code reliability.

I personally don't trust TS because it breaks when it targets ES5 and I
cannot control what other people target, but I would trust the standard
path and tools aiming at all cost to trample it right, whenever transpiring
is needed.

With Edge moving to use Chrome, and Firefox and WebKit always catching up,
these days introducing anything new might need transpilers just for a
couple of years, instead of decades.

Best Regards





On Mon, Mar 25, 2019 at 9:55 AM Naveen Chawla  wrote:

> Yes the real value of strict types, in my view, is at development time,
> not at run time.
>
> However I would be curious to know if anybody has a usage for them at run
> time, and an example of such a case...
>
> Otherwise, yes a "toolchain" that allows strict typing using JavaScript
> without having to "use TypeScript".
>
> On Mon, 25 Mar 2019 at 04:58, Ranando King  wrote:
>
>> One thing is definitively true. Any static type system added to ES must
>> not be mandatory. Untyped code must be able to call typed code without
>> forcing references into a fixed type. Likewise, typed code must be able to
>> call untyped code without forcing references to give up type guarantees.
>>
>> On Sun, Mar 24, 2019 at 8:48 PM kai zhu  wrote:
>>
>>> i share a similar concern that static-typing makes little sense in
>>> high-churn-rate UX-workflow-programming.
>>>
>>> it encourage people to bikeshed for correctness, on low-level code that
>>> frequently gets rewritten every few weeks/months -- and with often
>>> demoralizing effects.
>>>
>>> > On 24 Mar 2019, at 17:26, Bergi  wrote:
>>> >
>>> > Hello,
>>> > to play the devils advocate: why does JavaScript need static typing?
>>> >
>>> > Your proposal doesn't really answer that. Sure, it mentions tooling and
>>> > IDEs that can provide you with type hints and complain on mistakes, but
>>> > things like Flow and Typescript do this today already.
>>> > What's your goal, to have JS engines run Typescript(-like) code
>>> natively
>>> > without transpiling? For backwards-compatibility you'd have to do that
>>> > anyway, especially if new type system features are introduced
>>> incrementally.
>>> >
>>> > What's the point of building this feature into engines? It just
>>> provides
>>> > additional complexity. Not to mention the difficulty of finding a
>>> > suitable type system that is both sophisticated enough to describe all
>>> > useful code (not taking away too much flexibility) and simple enough to
>>> > understand without a CS degree. And which interfaces well with un-typed
>>> > completely dynamic code.
>>> >
>>> > What does "static typing" even mean to you in a dynamic scripting
>>> > language? JavaScript is not compiled by the developer, it is run by the
>>> > user. Where (when) do you expect types to be checked? Should the engine
>>> > throw early errors (during parsing)? During parsing of which parts of
>>> > the code, even when "normal" (untyped) code is calling into typed code?
>>> > Or do you expect dynamic runtime errors, like when assigning an invalid
>>> > value to a "typed variable"

Re: Proposal: Static Typing

2019-03-24 Thread Andrea Giammarchi
Just my personal thoughts on this.

The way PHP migrated to types has been thought incremental steps, and it
worked pretty well.

Since types have been demanded by the JS community for a while, I think
it'd be key to approach JS types not all at once, but through smaller
iterations.

As example, a proposal with a whole section entitled "Other useless things"
would easily diverge focus to stuff the is really not necessary at this
point.

Since types are also pretty much only a tooling convention, starting just
with the most basic need/help, and iterate more complex cases later on,
would be probably the best way to go.

Reading though all suggestions, I personally think these would be a no
brainer to specify and ship as first iteration:

   - primitives mean primitives (i.e. `string` means `typeof "string"`, no
   strings attached)
   - Classes and Built-ins mean classes and built-ins (i.e` String` means
   any `instanceof String`)
   - enum could be a new primitive (as in `typeof "enum"`, since static and
   immutable) but also an expression (like classes), for enums defined as
   properties/fields of literals and classes
   - I actually like the `auto` name more than `any`, but without signature
   overloads/rides the use case would be too broad, so that maybe we should
   have a way to also define multiple types (i.e. `const notFullyAuto:
   String|Object|string = value;`)
   - while I know it's pretty common to have `number[]` as type to define
   an array of numbers, I also don't understand why a new syntax should have
   already two different ways to define typed array, i.e. `const
   list:number[]` and `const list:[number]`, so since the latter one is more
   powerful/flexible, to define also multiple key/value pairs, maybe that's
   all we need

With these basics, the JS world would already have a huge change.

Things we might consider, but me might also don't care about, since these
behaviors are part of the specs:

   - `object` would accept `null`, but since there is no `typeof "null"`,
   the way to ensure `null` won't be there is to use `Object` instead. Are we
   OK with that?
   - `number` would accept `NaN` and `-/Infinity`, but IMO that's the case
   also without types, if a number is expected. Are we OK with that?
   - to avoid confusion with binary `|` operations, maybe multiple types
   could be wrapped in brackets, so that `const index:{number|string}` might
   look better?

That's it for my idea on how this could start moving forward.

Best Regards





On Sat, Mar 23, 2019 at 9:37 PM IdkGoodName Vilius <
viliuskubilius...@gmail.com> wrote:

> This is a proposal for static typing. Here is the github repository link:
> https://github.com/CreatorVilius/Proposal-Static-Typing
> I think it would be great thing in JS.
> ___
> 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: Loose idea on "try import"

2019-03-01 Thread Andrea Giammarchi
honestly this look like an `or` would've been great as reserved

try import fs from 'fs'
 or import fs from 'fs-polyfill'
 or import fs from 'another-fs-polyfill'
 catch optional, and triggered only if previous 3 imports failed
 finally optionally do something;

On Fri, Mar 1, 2019 at 12:05 PM Michał Wadas  wrote:

> Syntax:
>
> try import fs from 'fs'
>else import fs from 'fs-polyfill'
>else import fs from 'another-fs-polyfill'
>else do nothing; // Not sure about syntax
>
>
> try import {watchDirectory} from 'fs'
>else import {watchDirectory} from 'fs-polyfill'
>else if(process.os === 'ExoticSystem') import {watchDirectory} from
> 'another-fs-polyfill'
>else throw Error('Your OS doesn\'t support watching directories');
>
> Usages:
>
>- Optional dependencies
>- Polyfills
>
> Problems:
>
>- This can prevent loading modules before execution if presence of
>modules can't be proved statically
>- else-if requires execution before loading module - can be dropped
>
>
> I don't have enough time and knowledge about modules to write actual
> proposal.
> ___
> 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: `Object.isEmpty(value)`

2019-02-14 Thread Andrea Giammarchi
> 1. If `value` is either `null` or `undefined`, it gracefully falls back
to `false` instead of throwing an error.

I am having hard time logically thinking of an empty void as false:

Object.isEmpty(void 0) is false ?

I think keys(o || {}).length === 0 is a more explicit, ambiguity free,
alternative.

isEmpty(null) === false when typeof null is still object also doesn't feel
too right.


On Thu, Feb 14, 2019 at 7:31 AM Isiah Meadows 
wrote:

> This would be roughly equivalent to `Object.keys(value).length === 0`,
> but with a few exceptions:
>
> 1. If `value` is either `null` or `undefined`, it gracefully falls
> back to `false` instead of throwing an error.
> 2. It takes enumerable symbols into account, like `Object.assign`.
>
> So more accurately, it returns `false`  if the value is neither `null`
> nor `undefined` and has an own, enumerable property, or `true`
> otherwise.
>
> It's something I sometimes use when dealing with object-based hash
> maps (like what you get from JSON, input attributes). I typically fall
> back to the (partially incorrect) `for ... in` with a `hasOwnProperty`
> check for string keys, but I'd like to see this as a built-in.
>
> There's also a performance benefit: engines could short-circuit this
> for almost everything with almost no type checks. It's also an obvious
> candidate to specialize for types.
>
> - If it's not a reference type (object or function), return `true`.
> - If it's not a proxy object, or a proxy object that doesn't define
> `getPropertyDescriptor` or `ownKeys`, it's often just a memory load,
> even with dictionary objects and arrays.
> - If it's a proxy object with `ownKeys` and/or
> `getOwnPropertyDescriptor`, this is the slow path, but you can still
> short-circuit when `ownKeys` returns an empty array.
>
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
> ___
> 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: Bind function without thisArg

2019-01-14 Thread Andrea Giammarchi
The transpilation is what everyone publishing Web Apps/pages do these days,
it's not needed but most developers don't care, they mostly use whatever
bundler default is there.

The **main** lack of ECMAScript feature is a method that is not based on
new syntax, doesn't leak arguments, and transform these into an Array.

My proposed `slice.apply(index, arguments)` is still not used by
transopilers to solve forever in one place the issue so that production
code is full of unnecessary boilerplate every single time some dev uses
rest parameters for any callback.

If there was a method, not based on new syntax, able to be called through
`fn.apply(fn, arguments)` so that arguments wouldn't leak, and transpilers
can use a single polyfill as entry point to provide that ability, no extra
boilerplate would be ever need in production code.

I hope what I've said makes sense 👋




On Mon, Jan 14, 2019 at 4:49 PM Boris Zbarsky  wrote:

> On 1/14/19 9:47 AM, Andrea Giammarchi wrote:
> > rather because of the bloat it produces once transpiled:
>
> Hold on.
>
> The transpiling is necessary because of lack of what features in
> implementations?
>
> And what is the set of implementations that will lack those features but
> support bindArgs?
>
> (None of that is an argument against having bindArgs in core per se; I'm
> just trying to understand the transpiling issue here.)
>
> -Boris
> ___
> 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: Bind function without thisArg

2019-01-14 Thread Andrea Giammarchi
It's not so easy to implement in user land, not because it's difficult to
do so:

```js
Function.prototype.bindArgs = (...args) => {
  const fn = this;
  return function (...moar) {
return fn.apply(this, args.concat(moar));
  };
};
```

rather because of the bloat it produces once transpiled:
https://bit.ly/2SULtFZ

To avoid bloat and `arguments` leaking here and there, one must write
something like:

```js
function slice() {
  const arr = [];
  for (let {length} = arguments, i = +this; i < length; i++)
arr.push(arguments[i]);
  return arr;
}

Function.prototype.bindArgs = function () {
  const args = slice.apply(0, arguments);
  return function () {
const moar = slice.apply(0, arguments);
return fn.apply(this, args.concat(moar));
  };
};
```

which is still a hell of a boilerplate compared to a native `const ba =
fn.bindArgs.apply(fn, arguments);` or `fn.bindArgs(...arguments)` for short.

+1 for having this in core


On Mon, Jan 14, 2019 at 12:48 PM T.J. Crowder <
tj.crow...@farsightsoftware.com> wrote:

> Although this is easy enough to implement in userland, frankly so was
> `bind`. I'd say it comes up often enough to consider. PrototypeJS (remember
> PrototypeJS?) called it `curry`.
>
> I'd think the specification changes for it would be minimal as well,
> basically A) Allowing Empty as boundThis in BoundFunctionCreate and
> [[BoundThis]] on functions; B) Updating [[Call]] on Bound Functions to use
> thisArgument when boundThis is Empty; creating a new `Function.prototype`
> method (`curry` would be the obvious -- and almost certainly **not**
> websafe -- name) to call BoundFunctionCreate with Empty for boundThis.
>
> But I'd be interested to know how difficult it is for JavaScript engines
> to implement, since Empty is largely a spec-level concept and it's valid
> (in strict mode) to use `null` and `undefined` as boundThis...
>
> -- 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: Proposal: Add `NoSubstitutionTemplate` to `StringLiteral` Definition

2019-01-09 Thread Andrea Giammarchi
I dare saying tags are another issue here, 'cause "abc" === "abc", and with
an identity function such `const id = o => o`, `id("abc") === id("abc")`
but due latest changes to template literals, id`abc` !== id`abc` so it's
easily misleading in the tagged case.

On Wed, Jan 9, 2019 at 7:53 PM Jordan Harband  wrote:

> import path specifiers are another.
>
> On Wed, Jan 9, 2019 at 10:16 AM T.J. Crowder <
> tj.crow...@farsightsoftware.com> wrote:
>
>> On Wed, Jan 9, 2019 at 5:36 PM FERREIRA, ERIC B
>>  wrote:
>> > I contend that adding `NoSubstitutionTemplate`s to the definition of
>> > `StringLiteral` will bring the benefit of allowing teams to
>> > completely opt to use only template strings instead of mixing quote
>> > marks, while having very little risk or downside, if any at all.
>>
>> I've been toying with defaulting to template literals for some time. :-)
>>
>> Interesting idea. Where specifically do you see benefits of this
>> change? The only places that immediately jump out to me are
>>
>> * "use strict", mentioned in your linked article
>> * Quoted property names in object initializers (aka "object literals")
>> -- oddly not mentioned in that article (it mentions JSON, but not
>> object initializers)
>>
>> That second one could be a bit of a footgun for people, who may trip
>> over this working:
>>
>> ```js
>> const obj = {`I have a space`: `bar`};
>> ```
>>
>> ...but this failing:
>>
>> ```js
>> const obj = {`I have a space ${x}`: `bar`};
>> ```
>>
>> ...because that's not a NoSubstitutionTemplate and so it needs to be a
>> computed property name.
>>
>> Are there other places?
>>
>> -- 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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Array.prototype.count

2019-01-07 Thread Andrea Giammarchi
[time to write specs, pass through the whole process, ship it to all
engines, have it 100% usable without polyfills]

[value of this proposal]

both sentences represents time, -1 here

On Mon, Jan 7, 2019 at 8:35 PM Ranando King  wrote:

> Either way it goes, there's a lot of ways to do this that are all trivial.
>
> On Mon, Jan 7, 2019 at 1:31 PM Pier Bover  wrote:
>
>> If you need to find the length of a filtered array IMO it makes more
>> sense and is more obvious to just use filter().
>>
>> On Mon, Jan 7, 2019 at 1:12 PM Засим Александр 
>> wrote:
>>
>>> Hi everyone. This is proposal for Array.prototype.count (or countOf)
>>> method which allow to count specific elements in an array.
>>>
>>> ```js
>>>
>>> const evenNumberCount = [1, 2, 3, 4, 5].count(num => num % 2 === 0);
>>>
>>> ```
>>>
>>> Instead of
>>>
>>> ```js
>>>
>>> const evenNumberCount = [1, 2, 3, 4, 5].filter(num => num % 2 ===
>>> 0).length;
>>>
>>> ```
>>> ___
>>> 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
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: String identity template tag

2018-12-13 Thread Andrea Giammarchi
FWIW, I've used same logic for something like a no-op for i18n`strings` [1]
so, considering it has easily use cases with mapped interpolations too, I
think it's more than natural to have that in core.

It's also backward compatible/polyfillable so this is kinda a no-brainer,
name a part, of course.

[1] https://github.com/WebReflection/i18n-dummy/blob/master/index.js

On Thu, Dec 13, 2018 at 6:15 PM T.J. Crowder <
tj.crow...@farsightsoftware.com> wrote:

> In general, I think method names should be verbs in the imperative
> tense (okay, *mood* if you like linguistic distinctions), which would
> argue for `cook` rather than `cooked`. (`String.raw` is an unfortunate
> exception to this rule, which has largely been used throughout the
> standard library. Another exception is `Reflect.ownKeys`. There are
> probably others as well, but they are exceptions, not the norm.)
>
> I like `cook`. It's `assemble`, but with more flavor.
>
> The good news here, though, is we're all talking about a name, which
> suggests that in general people like the taste of the idea. There
> don't seem to be concerns that it's half-baked.
>
> (I'll stop now.)
>
> -- 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: String identity template tag

2018-12-12 Thread Andrea Giammarchi
I agree with Mark, and I wonder why `String.tag` is not the obvious choice
here, since every interpolation is also coerced as String

On Thu, Dec 13, 2018 at 9:34 AM Isiah Meadows 
wrote:

> I mean equivalence to untagged behavior, if that helps.
>
> FWIW, as stated previously, I'm not married to the name.
> On Wed, Dec 12, 2018 at 20:31 Mark Miller  wrote:
>
>>
>> On Wed, Dec 12, 2018 at 5:24 PM Isiah Meadows 
>> wrote:
>>
>>> The template is being expanded as if the template itself is untagged.
>>
>>
>> Does this mean that you describe what tagged templates do, or what
>> untagged templates do, as "expanding" something? If so, what is the
>> intuition behind that prior usage of "expand"?
>>
>>
>>
>>> The point of this is a template tag that just does the default untagged
>>> behavior of coercing all expressions to strings and joining the whole thing
>>> together.
>>>
>>
>> I certainly agree that the name should suggest equivalence to the default
>> untagged behavior. I just never would have thought to describe that
>> behavior as "expanding" something. What is it expanded into?
>>
>>
>>
>>> On Wed, Dec 12, 2018 at 20:21 Mark Miller  wrote:
>>>
 What is the intuition behind "expand"? What is being expanded, and what
 is it expanding into?



 On Tue, Dec 11, 2018 at 10:59 PM Isiah Meadows 
 wrote:

> Those names a little too generic for my liking here. What about
> `String.expand(template, ...params)`?
>
> And also, let's not try to bake a traditional template engine into the
> JS spec - syntactic template strings already work well enough.
>
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
>
> On Wed, Dec 12, 2018 at 1:13 AM Michael Luder-Rosefield
>  wrote:
> >
> > Why not String.tag or .tagged?
> >
> > While we're at it, is there any good reason not to have something
> like this:
> >
> > ```
> > String.template = (template : String,
> taggerFn=String.identity/tag/tagged : Function) => (keys : Array | Object)
> => taggerFn(template, (keys is Array) ? ...keys : keys)
> > // apologies for pseudo-semi-functional code
> > // having keys be an object allows template to be filled by key name
> rather than just index
> > ```
> > This would make templates closer to the traditional usage, where the
> template comes first and is later passed values to be filled in with.
> Having the taggerFn as an argument allows for things like Isiah's
> escape-then-apply tagging examples.
> >
> >
> > On Wed, 12 Dec 2018 at 12:51 Isiah Meadows 
> wrote:
> >>
> >> I'm not married to `identity`, and I agree the name is probably not
> >> ideal. I'm more concerned about functionality, though.
> >>
> >> -
> >>
> >> Isiah Meadows
> >> cont...@isiahmeadows.com
> >> www.isiahmeadows.com
> >>
> >> On Tue, Dec 11, 2018 at 5:41 AM T.J. Crowder
> >>  wrote:
> >> >
> >> > On Mon, Dec 10, 2018 at 7:08 PM Isiah Meadows
> >> >  wrote:
> >> > >
> >> > > It'd be *way* easier to construct simple template tags if there
> was a
> >> > > built-in identity tag
> >> >
> >> > Wholeheartedly agree, a couple of months ago I considered posting
> something very similar, both for utility reasons and in hopes that it 
> would
> be an optimization target (being a standard operation).
> >> >
> >> > I find the name `identity` unilluminating, though, partially
> because it's not quite the same meaning as the usual "identity" function
> (`function identity(x) { return x; }`), though it's close. `assemble`?
> >> >
> >> > -- 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
>


 --
   Cheers,
   --MarkM

>>>
>>
>> --
>>   Cheers,
>>   --MarkM
>>
> ___
> 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: Callable objects protocol

2018-12-05 Thread Andrea Giammarchi
I don't think introducing `public` here has any value. We have `static #a =
1` eventually for private already, the default should follow the classes
behavior, IMO

On Wed, Dec 5, 2018 at 10:46 PM Ranando King  wrote:

> That's the kind of thing I was shooting for with static lexical scope
> variables. There's 2 problems with it given the way things are going
> though. Take a look.
>
> ```js
> function foo() {
>   static a=1,
>  b=2,
>  c=3;
> }
> ```
> By the way I'm thinking, this would create 3 static variables within foo
> that are only initialized once and retain whatever value is set on them
> across invocations. Basically, the object `foo` carries around a closure
> containing those values. Problem is, this is private to foo. That conflicts
> with class-fields and it's sigil-means-private model.
>
> Ignoring that, public static variables can also be done (but it'd be the
> first ever introduction of `public` in ES.
> ```js
> function foo() {
>   static public a=1,
> b=2,
> c=3;
> }
> ```
> This would make `foo.a`, `foo.b`, & `foo.c` accessible as public
> properties of `foo`.
>
> Think this needs to be a proposal?
>
>
> On Wed, Dec 5, 2018 at 1:39 AM Isiah Meadows 
> wrote:
>
>> Personally, I'd prefer something else: a means of a function object
>> literal that's still callable, but I can tack other properties to it
>> easily. Something like this, maybe:
>>
>> ```js
>> {
>> (...args) { ... },
>> }
>> ```
>>
>> In this, the `this` value is set to the callee itself, not the given
>> `this` value.
>>
>> Not married to the syntax, but I want the functionality.
>> On Wed, Dec 5, 2018 at 01:34 Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> > the apply hook needs objects anyway.
>>>
>>> I meant functions
>>>
>>> On Wed, Dec 5, 2018 at 1:33 PM Andrea Giammarchi <
>>> andrea.giammar...@gmail.com> wrote:
>>>
>>>> I've actually replied to the op, I didn't mean to answer you directly,
>>>> but the only reason I wrote that is because I could, no other reasons.
>>>>
>>>> However, people unaware of the handleEvent pattern for event listeners
>>>> often hope to be able to pass objects as listeners, ignoring the fact they
>>>> can do that already (but they need a handleEvent method, own or inherited,
>>>> in that object).
>>>>
>>>> There is at least another use case I can't remember now, but I do
>>>> remember doing the Proxy dance before ending up realizing that the apply
>>>> hook needs objects anyway.
>>>>
>>>> But yeah, I don't think it's a must have, specially because we can have
>>>> something similar already, as shown in my example.
>>>>
>>>>
>>>> On Wed, Dec 5, 2018 at 1:25 PM Ranando King  wrote:
>>>>
>>>>> Maybe I asked it wrong.
>>>>>
>>>>> How is making an ordinary object callable at all useful for anything
>>>>> that can't already be easily handled via objects and functions? (looking
>>>>> for use cases here)
>>>>> How does this make coding easier to do and understand? (for the AST
>>>>> parser and for the human)
>>>>>
>>>>> On Tue, Dec 4, 2018 at 11:54 PM Andrea Giammarchi <
>>>>> andrea.giammar...@gmail.com> wrote:
>>>>>
>>>>>> How about this:
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> // the poly
>>>>>> if (!Symbol.callable)
>>>>>>   Symbol.callable = Symbol('callable');
>>>>>>
>>>>>> // the setup
>>>>>> class Callable extends Function {
>>>>>>   constructor(object) {
>>>>>> super('return arguments.callee[Symbol.callable](...arguments)');
>>>>>> //sloppy mode FTW!
>>>>>> Object.setPrototypeOf(this, object);
>>>>>>   }
>>>>>> }
>>>>>>
>>>>>>
>>>>>> // the example
>>>>>> const obj = new Callable({
>>>>>>   [Symbol.callable](value) {
>>>>>> return value + this.value;
>>>>>>   },
>>>>>>   value: 123
>>>>>> });
>>>>>>
>>>>>> obj(7); // 130
>>>>>>
>>>>>>
>>>>>> ```
>>>>>>
>>>>>> On Wed, Dec 5, 2018 at 12:02 AM Sultan  wrote:
>>>>>>
>>>>>>> Something along the lines of Symbol.iterator protocol for defining
>>>>>>> callback objects i.e: Symbol.callable:
>>>>>>>
>>>>>>> const obj = {
>>>>>>> [Symbol.callable]: function (...args) { return
>>>>>>> this[Symbol.for('value')] },
>>>>>>> [Symbol.for(''value')]: 'value',
>>>>>>> }
>>>>>>>
>>>>>>> assert(obj() === 'value')
>>>>>>> ___
>>>>>>> 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
>>>
>>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Callable objects protocol

2018-12-04 Thread Andrea Giammarchi
> the apply hook needs objects anyway.

I meant functions

On Wed, Dec 5, 2018 at 1:33 PM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> I've actually replied to the op, I didn't mean to answer you directly, but
> the only reason I wrote that is because I could, no other reasons.
>
> However, people unaware of the handleEvent pattern for event listeners
> often hope to be able to pass objects as listeners, ignoring the fact they
> can do that already (but they need a handleEvent method, own or inherited,
> in that object).
>
> There is at least another use case I can't remember now, but I do remember
> doing the Proxy dance before ending up realizing that the apply hook needs
> objects anyway.
>
> But yeah, I don't think it's a must have, specially because we can have
> something similar already, as shown in my example.
>
>
> On Wed, Dec 5, 2018 at 1:25 PM Ranando King  wrote:
>
>> Maybe I asked it wrong.
>>
>> How is making an ordinary object callable at all useful for anything that
>> can't already be easily handled via objects and functions? (looking for use
>> cases here)
>> How does this make coding easier to do and understand? (for the AST
>> parser and for the human)
>>
>> On Tue, Dec 4, 2018 at 11:54 PM Andrea Giammarchi <
>> andrea.giammar...@gmail.com> wrote:
>>
>>> How about this:
>>>
>>> ```js
>>>
>>> // the poly
>>> if (!Symbol.callable)
>>>   Symbol.callable = Symbol('callable');
>>>
>>> // the setup
>>> class Callable extends Function {
>>>   constructor(object) {
>>> super('return arguments.callee[Symbol.callable](...arguments)');
>>> //sloppy mode FTW!
>>> Object.setPrototypeOf(this, object);
>>>   }
>>> }
>>>
>>>
>>> // the example
>>> const obj = new Callable({
>>>   [Symbol.callable](value) {
>>> return value + this.value;
>>>   },
>>>   value: 123
>>> });
>>>
>>> obj(7); // 130
>>>
>>>
>>> ```
>>>
>>> On Wed, Dec 5, 2018 at 12:02 AM Sultan  wrote:
>>>
>>>> Something along the lines of Symbol.iterator protocol for defining
>>>> callback objects i.e: Symbol.callable:
>>>>
>>>> const obj = {
>>>> [Symbol.callable]: function (...args) { return
>>>> this[Symbol.for('value')] },
>>>> [Symbol.for(''value')]: 'value',
>>>> }
>>>>
>>>> assert(obj() === 'value')
>>>> ___
>>>> 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: Callable objects protocol

2018-12-04 Thread Andrea Giammarchi
I've actually replied to the op, I didn't mean to answer you directly, but
the only reason I wrote that is because I could, no other reasons.

However, people unaware of the handleEvent pattern for event listeners
often hope to be able to pass objects as listeners, ignoring the fact they
can do that already (but they need a handleEvent method, own or inherited,
in that object).

There is at least another use case I can't remember now, but I do remember
doing the Proxy dance before ending up realizing that the apply hook needs
objects anyway.

But yeah, I don't think it's a must have, specially because we can have
something similar already, as shown in my example.


On Wed, Dec 5, 2018 at 1:25 PM Ranando King  wrote:

> Maybe I asked it wrong.
>
> How is making an ordinary object callable at all useful for anything that
> can't already be easily handled via objects and functions? (looking for use
> cases here)
> How does this make coding easier to do and understand? (for the AST parser
> and for the human)
>
> On Tue, Dec 4, 2018 at 11:54 PM Andrea Giammarchi <
> andrea.giammar...@gmail.com> wrote:
>
>> How about this:
>>
>> ```js
>>
>> // the poly
>> if (!Symbol.callable)
>>   Symbol.callable = Symbol('callable');
>>
>> // the setup
>> class Callable extends Function {
>>   constructor(object) {
>> super('return arguments.callee[Symbol.callable](...arguments)');
>> //sloppy mode FTW!
>> Object.setPrototypeOf(this, object);
>>   }
>> }
>>
>>
>> // the example
>> const obj = new Callable({
>>   [Symbol.callable](value) {
>> return value + this.value;
>>   },
>>   value: 123
>> });
>>
>> obj(7); // 130
>>
>>
>> ```
>>
>> On Wed, Dec 5, 2018 at 12:02 AM Sultan  wrote:
>>
>>> Something along the lines of Symbol.iterator protocol for defining
>>> callback objects i.e: Symbol.callable:
>>>
>>> const obj = {
>>> [Symbol.callable]: function (...args) { return
>>> this[Symbol.for('value')] },
>>> [Symbol.for(''value')]: 'value',
>>> }
>>>
>>> assert(obj() === 'value')
>>> ___
>>> 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: Callable objects protocol

2018-12-04 Thread Andrea Giammarchi
How about this:

```js

// the poly
if (!Symbol.callable)
  Symbol.callable = Symbol('callable');

// the setup
class Callable extends Function {
  constructor(object) {
super('return arguments.callee[Symbol.callable](...arguments)');
//sloppy mode FTW!
Object.setPrototypeOf(this, object);
  }
}


// the example
const obj = new Callable({
  [Symbol.callable](value) {
return value + this.value;
  },
  value: 123
});

obj(7); // 130


```

On Wed, Dec 5, 2018 at 12:02 AM Sultan  wrote:

> Something along the lines of Symbol.iterator protocol for defining
> callback objects i.e: Symbol.callable:
>
> const obj = {
> [Symbol.callable]: function (...args) { return
> this[Symbol.for('value')] },
> [Symbol.for(''value')]: 'value',
> }
>
> assert(obj() === 'value')
> ___
> 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: What is holding back Decorators ?

2018-12-04 Thread Andrea Giammarchi
Btw, I don't care 'cause I find the inline syntax to export a class ugly in
either ways so I hope that is not a blocker 'cause I don't see it a real
blocker in the real world, while not having decorators is a real issue in
the real world.

Thanks for moving forward.

Best Regards

On Wed, Dec 5, 2018 at 7:44 AM Andrea Giammarchi <
andrea.giammar...@gmail.com> wrote:

> It's well known that twitter users pay a lot of attention to details, vote
> only once they've understood the issue and their own opinions about
> technical matters, and follow closer this channel since ever ...
>
>
>
> On Wed, Dec 5, 2018 at 2:18 AM T.J. Crowder <
> tj.crow...@farsightsoftware.com> wrote:
>
>> On Tue, Dec 4, 2018 at 7:08 PM T.J. Crowder
>>  wrote:
>> >
>> > I believe there already is one:
>> > https://github.com/tc39/proposal-decorators/issues/69
>>
>> Apparently there was a poll (**really** wish someone had mentioned it
>> here, following ALL contributors to proposals on twitter is not
>> scalable):
>> https://twitter.com/littledan/status/1050815837962158080
>>
>> The @dec export got 36% vs. export @dec at 22 with 29% saying they
>> don't care which.
>>
>> -- T.J. Crowder
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


  1   2   3   4   5   6   7   8   9   10   >