Re: Proposal: switch expressions

2019-03-01 Thread Isiah Meadows
> It would be unthinkable for it to use pattern matching or explicit code 
> branching instead of method inheritance for type disambiguation during render

But it frequently does internally. For example:

- Calculating object projections:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L1243-L1351
- Rendering object *lists*:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L1353-L1411
- Setting the rendering mode and controlling basic rendering:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L802-L874

Obviously, it exposes a data-oriented, object oriented API. And it
does appear it's not *exclusively* conditionals:

- It invokes an dynamic `render` method for "immediate render
objects": 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L636-L644
- In `renderBufferDirect`, it does virtual method dispatch on `render`
based on one of two possible types, but it otherwise uses conditionals
for everything:\*
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L707-L876
- It uses a fair bit of functional programming in `compile`:
https://github.com/mrdoob/three.js/blob/dev/src/renderers/WebGLRenderer.js#L1009-L1054

However, I'm finding exceptions in its core and renderers, and it
doesn't appear virtual dispatch is *that* broadly and pervasively
used, even though it uses methods a lot.

\* This seems like overkill when the diff between the two renderers in
question [1] [2] consist of an extra method + 2 extra variables [3]
[4], a few changed method invocations [5] [6], and the rest just due
to a different name and a useless `var`.

[1]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLBufferRenderer.js
[2]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js
[3]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L15-L22
[4]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L61
[5]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L26
[6]: 
https://github.com/mrdoob/three.js/blob/dev/src/renderers/webgl/WebGLIndexedBufferRenderer.js#L53

> I'm curious where you got the idea that method invocation is "far" slower 
> than explicit code branching?

- In C++: https://stackoverflow.com/a/8866789
- JS benchmark with 4 variants (typed method dispatch is polymorphic):
http://jsben.ch/fbJQH
- JS benchmark with 12 variants (typed method dispatch is
megamorphic): http://jsben.ch/aWNDN

And in my experience, the speed difference in real-world
performance-critical code is not unlike that microbenchmark and is
sometimes even more drastic, especially if it's a linked list instead
of just a simple array lookup.

I'd like to emphasize I'm specifically referring to the case where the
engine can't reliably assume a single method receiver, i.e. when it
*has* to fall back to dynamic dispatch.

-

Isiah Meadows
cont...@isiahmeadows.com
www.isiahmeadows.com

On Fri, Mar 1, 2019 at 6:25 AM Naveen Chawla  wrote:
>
> The entire renderers, cameras, meshes etc. hierarchy uses method inheritance 
> and many of those methods are called during scene rendering (which is 
> performance sensitive as it happens per frame). It would be unthinkable for 
> it to use pattern matching or explicit code branching instead of method 
> inheritance for type disambiguation during render, because it would explode 
> the code as well as making it error prone due to initial cases potentially 
> unintentionally swallowing up cases intended for later code branches (or 
> unintentionally repeating code branches if the pattern-matching proposal 
> doesn't have "else" behaviour, of which I'm not sure, but it if does, it 
> suffers from the first problem anyway).
>
> I'm curious where you got the idea that method invocation is "far" slower 
> than explicit code branching?
>
> On Thu, 28 Feb 2019 at 18:49 Isiah Meadows  wrote:
>>
>> I'm looking at Three.js's code base, and I'm not seeing any method
>> overriding or abstract methods used except at the API level for
>> cloning and copying. Instead, you update properties on the supertype.
>> As far as I can tell, the entirety of Three.js could almost be
>> mechanically refactored in terms of components instead of inheritance,
>> without substantially modifying the API apart from a few extra
>> `.geometry`/etc. property accesses when calling supertype methods.
>> It's data-driven and almost ECS. (It uses `.isObject3D`,
>> `.isPerspectiveCamera`, and similar brand checks, but those don't
>> *need* to be inherited to work.)
>>
>> -
>>
>> Isiah Meadows
>> cont...@isiahmeadows.com
>> www.isiahmeadows.com
>>
>> On Thu, Feb 28, 2019 at 12:40 PM Naveen Chawla  wrote:
>> >
>> > I'm not sure that pattern matching handles deep levels of inheritance more 
>> > elegantly than inheritance itself.
>> >

Re: Loose idea on "try import"

2019-03-01 Thread Isiah Meadows
Personally, I find this a *bad* idea. Top-level `await` in modules
would solve this problem far more quickly and efficiently.

-

Isiah Meadows
cont...@isiahmeadows.com
www.isiahmeadows.com

On Fri, Mar 1, 2019 at 3:35 PM Ben Wiley  wrote:
>
> Has anyone seen anything like this done in another language (with static 
> imports)? If so we could learn something maybe. I know you can conditionally 
> import in Python but that's basically the same thing as .catch()ing dynamic 
> import()s in JavaScript (except done synchronously).
>
> Ben
>
> Le ven. 1 mars 2019 15 h 26, Herby Vojčík  a écrit :
>>
>> On 1. 3. 2019 18:35, Michał Wadas wrote:
>> > I don't think so, because:
>> >
>> >   * Using promises to import module is not always desirable
>> >   * This mechanism doesn't impact ability to statically analyze modules
>> > if ifs are excluded - it can only increase resolution time.
>>
>> Yeah, if 'if's are excluded. That version with those ifs was what was
>> concerning. That actually needs runtime to do the work. I suppose until
>> it doesn't need the runtime, it's all ok.
>>
>> >
>> > On Fri, Mar 1, 2019 at 1:56 PM Herby Vojčík > > > wrote:
>> >
>> > On 1. 3. 2019 12:04, 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');
>> >
>> > I am not an expert, but afaict ES module system was created to be
>> > statically analysable and this bring uncertainity.
>> >
>> > For that probably dynamic import() is there; and your usage should
>> > await
>> > for a promise that tries to load one then the other etc.
>> >
>> > Herby
>> >
>> >  > 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
___
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 Ben Wiley
Has anyone seen anything like this done in another language (with static
imports)? If so we could learn something maybe. I know you can
conditionally import in Python but that's basically the same thing as
.catch()ing dynamic import()s in JavaScript (except done synchronously).

Ben

Le ven. 1 mars 2019 15 h 26, Herby Vojčík  a écrit :

> On 1. 3. 2019 18:35, Michał Wadas wrote:
> > I don't think so, because:
> >
> >   * Using promises to import module is not always desirable
> >   * This mechanism doesn't impact ability to statically analyze modules
> > if ifs are excluded - it can only increase resolution time.
>
> Yeah, if 'if's are excluded. That version with those ifs was what was
> concerning. That actually needs runtime to do the work. I suppose until
> it doesn't need the runtime, it's all ok.
>
> >
> > On Fri, Mar 1, 2019 at 1:56 PM Herby Vojčík  > > wrote:
> >
> > On 1. 3. 2019 12:04, 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');
> >
> > I am not an expert, but afaict ES module system was created to be
> > statically analysable and this bring uncertainity.
> >
> > For that probably dynamic import() is there; and your usage should
> > await
> > for a promise that tries to load one then the other etc.
> >
> > Herby
> >
> >  > 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: Loose idea on "try import"

2019-03-01 Thread Herby Vojčík

On 1. 3. 2019 18:35, Michał Wadas wrote:

I don't think so, because:

  * Using promises to import module is not always desirable
  * This mechanism doesn't impact ability to statically analyze modules
if ifs are excluded - it can only increase resolution time.


Yeah, if 'if's are excluded. That version with those ifs was what was 
concerning. That actually needs runtime to do the work. I suppose until 
it doesn't need the runtime, it's all ok.




On Fri, Mar 1, 2019 at 1:56 PM Herby Vojčík > wrote:


On 1. 3. 2019 12:04, 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');

I am not an expert, but afaict ES module system was created to be
statically analysable and this bring uncertainity.

For that probably dynamic import() is there; and your usage should
await
for a promise that tries to load one then the other etc.

Herby

 > 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


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: Loose idea on "try import"

2019-03-01 Thread Michał Wadas
I don't think so, because:

   - Using promises to import module is not always desirable
   - This mechanism doesn't impact ability to statically analyze modules if
   ifs are excluded - it can only increase resolution time.




On Fri, Mar 1, 2019 at 1:56 PM Herby Vojčík  wrote:

> On 1. 3. 2019 12:04, 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');
>
> I am not an expert, but afaict ES module system was created to be
> statically analysable and this bring uncertainity.
>
> For that probably dynamic import() is there; and your usage should await
> for a promise that tries to load one then the other etc.
>
> Herby
>
> > 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


Re: Proposal: export ** from './FooBar'

2019-03-01 Thread Mike Samuel
On Fri, Mar 1, 2019 at 1:35 AM Cyril Auburtin 
wrote:

> Sometimes, (particularly in React codebases) you have to write many lines
> like:
> ```js
> export { default as FooBar } from './FooBar';
> ```
> It could be automated of course
>
> It could also be tuned into
> ```js
> export * from './FooBar';
> ```
> only if FooBar is also a named export in that file, but usually files with
> one export just use a default export
>
> --
> This proposed syntax:
> ```js
> export ** from './FooBar';
> ```
> Would do:
> ```js
> export * from './FooBar';
> export { default as FooBar } from './FooBar';
> ```
> the filename is used as default export name.
>
> If the filename isn't a valid JS identifier, like 'foo-bar' for example,
> it would throw
>

ES doesn't impose many constraints on the string content of a module
specifier but in practice it maps fairly directly to a URL per
https://html.spec.whatwg.org/multipage/webappapis.html#hostgetimportmetaproperties
so filename is probably broadly available.

Would this use the filename from the module specifier or from the URL
(assuming import.meta.url)?
IIRC, only the module specifier is available within ES currently.
The translation between specifiers and URLs (if that happens) is up to a
host callback (HostResolveImportedModule) and does not surface inside the
ES engine.
That import.meta.url exists is up to another host callback so assuming it's
existence might require constraining host implementations of
HostGetMetaProperties(?).

What would this do when import.meta.url/specifier has a query part, or that
look like a non-hierarchical URL?
export ** from "path?foo=bar";
export ** from "?foo=bar";
export ** from "data:application/javascript+module,export default null;"

Does anyone know if existing CDNs use the path component for something
other than the path contributed by the uploader and expect the original
filename in the query, like
host.cdn/path/to/tarball?p=path/within/tarball.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 Herby Vojčík

On 1. 3. 2019 12:04, 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');


I am not an expert, but afaict ES module system was created to be 
statically analysable and this bring uncertainity.


For that probably dynamic import() is there; and your usage should await 
for a promise that tries to load one then the other etc.


Herby


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


Re: Proposal: switch expressions

2019-03-01 Thread Naveen Chawla
The entire renderers, cameras, meshes etc. hierarchy uses method
inheritance and many of those methods are called during scene rendering
(which is performance sensitive as it happens per frame). It would be
unthinkable for it to use pattern matching or explicit code branching
instead of method inheritance for type disambiguation during render,
because it would explode the code as well as making it error prone due to
initial cases potentially unintentionally swallowing up cases intended for
later code branches (or unintentionally repeating code branches if the
pattern-matching proposal doesn't have "else" behaviour, of which I'm not
sure, but it if does, it suffers from the first problem anyway).

I'm curious where you got the idea that method invocation is "far" slower
than explicit code branching?

On Thu, 28 Feb 2019 at 18:49 Isiah Meadows  wrote:

> I'm looking at Three.js's code base, and I'm not seeing any method
> overriding or abstract methods used except at the API level for
> cloning and copying. Instead, you update properties on the supertype.
> As far as I can tell, the entirety of Three.js could almost be
> mechanically refactored in terms of components instead of inheritance,
> without substantially modifying the API apart from a few extra
> `.geometry`/etc. property accesses when calling supertype methods.
> It's data-driven and almost ECS. (It uses `.isObject3D`,
> `.isPerspectiveCamera`, and similar brand checks, but those don't
> *need* to be inherited to work.)
>
> -
>
> Isiah Meadows
> cont...@isiahmeadows.com
> www.isiahmeadows.com
>
> On Thu, Feb 28, 2019 at 12:40 PM Naveen Chawla 
> wrote:
> >
> > I'm not sure that pattern matching handles deep levels of inheritance
> more elegantly than inheritance itself.
> >
> > If there is a conceptual type hierarchy, then the ability to call
> "super", combine it with specialized functionality, etc. is a lot more
> manageable using localized, separated logic where you don't feel forced to
> read "other patterns" to understand whether your target functionality will
> resolve correctly. And hence, a lower chance of bugs.
> >
> > As for performance, I'd have to see modern benchmarks. But it's not
> necessarily clear that pattern matching will be particularly fast either.
> I've done game programming with method overriding (Three.js uses it too
> throughout) and there is no notable performance hit from doing so. So I'm
> not clear where you have got this information from.
> >
> > On Thu, 28 Feb 2019 at 17:06 Isiah Meadows 
> wrote:
> >>
> >> > Using a "switch" here forces you to group classes of objects together
> and then you don't get the 2nd, 3rd, 4th etc. levels of specialization that
> you might later want.
> >>
> >> Sometimes, this is actually *desired*, and most cases where I could've
> >> used this, inheritance was not involved *anywhere*. Also, in
> >> performance-sensitive contexts (like games, which *heavily* use
> >> `switch`/`case`), method dispatch is *far* slower than a simple
> >> `switch` statement, so that pattern doesn't apply everywhere.
> >>
> >> BTW, I prefer https://github.com/tc39/proposal-pattern-matching/ over
> >> this anyways - it covers more use cases and is all around more
> >> flexible, so I get more bang for the buck.
> >>
> >> -
> >>
> >> Isiah Meadows
> >> cont...@isiahmeadows.com
> >> www.isiahmeadows.com
> >>
> >> On Thu, Feb 28, 2019 at 9:23 AM Naveen Chawla 
> wrote:
> >> >
> >> > Hi David!
> >> >
> >> > Your last example would, I think, be better served by classes and
> inheritance, than switch.
> >> >
> >> > Dogs are house animals which are animals
> >> > Cheetas are wild cats which are animals
> >> >
> >> > Each could have overridden methods, entirely optionally, where the
> method gets called and resolves appropriately.
> >> >
> >> > The input argument could be the class name, from which it is trivial
> to instantiate a new instance and get required results.
> >> >
> >> > Using a "switch" here forces you to group classes of objects together
> and then you don't get the 2nd, 3rd, 4th etc. levels of specialization that
> you might later want.
> >> >
> >> > All thoughts on this are welcome. Do let me know
> >> >
> >> > On Thu, 28 Feb 2019 at 14:06 David Koblas  wrote:
> >> >>
> >> >> Naveen,
> >> >>
> >> >> Thanks for your observation.  The example that I gave might have
> been too simplistic, here's a more complete example:
> >> >>
> >> >> ```
> >> >>
> >> >> switch (animal) {
> >> >> case Animal.DOG, Animal.CAT => {
> >> >> // larger block expression
> >> >> // which spans multiple lines
> >> >>
> >> >> return "dry food";
> >> >>   }
> >> >> case Animal.TIGER, Animal.LION, Animal.CHEETA => {
> >> >> // larger block expression
> >> >> // which spans multiple lines
> >> >>
> >> >> return "fresh meat";
> >> >>   }
> >> >> case Animal.ELEPHANT => "hay";
> >> >> default => { throw new Error("Unsupported Animal"); };
> >> >> }
> 

Loose idea on "try import"

2019-03-01 Thread Michał Wadas
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