Re: Strawman: `Function.prototype.try` (or `Function.try`)

2017-08-22 Thread Isiah Meadows
@all

BTW, I specifically avoided `type: "normal"`, etc., because only
`"normal"` and `"throw"` are exposed to JS in any significant capacity
- they're what you can detect using `try`/`catch`. The others are
internal-only exception-like values used in the spec to implement
breaking and loop continuation in its internal AST interpreter.
Although I said completions, I meant it loosely.

(All browser engines instead operate on control flow graphs to
generate bytecode, so they also only really use `"normal"` and
`"throw"`.)

In addition, monads are a great way of introducing complexity into the
language, and absent pattern matching *at all* (or anything else
similarly extensible), let's save that rabbit hole for another time.

Here's some more specific responses inline:

On Tue, Aug 22, 2017 at 1:21 PM, Jordan Harband  wrote:
> I think if we wanted to add a "Result" type, we might want to do that
> holistically instead of having an arbitrary prototype method return an
> arbitrary object literal.
>
> It'd be really nice to have that type, but I'm not sure how easy it'd be to
> make a compelling case.

I like this, but the complicated monadic whatnot that was
*immediately* suggested is quite frankly *not* the ideal way to handle
this, since we already have standard exception handling.

What about something like this, just to start? Of course, there's
probably big things missing here, but just thought I'd get the ball
rolling a little.

```js
class Result {
constructor(init: () => T);
value: any;
type: "return" | "throw";
get(): T; // throws if `init` threw
}
```

(I'd rather start small than wind up with something over-engineered
and really bad.)

On Tue, Aug 22, 2017 at 2:08 PM, Sebastian Malton 
> wrote:
>
> 1. What is the difference between "normal" and "return"?

You get `"return"` when returning from a function. The spec implements
early returns using this (a special exception-like completion), since
it just interpret's the AST directly.

Engines don't actually use this method, though. They build a control
flow graph, and they lower `let`s into something not unlike `var`s, so
they don't actually need to have anything like a special exception to
handle these cases.

> Since try catching is not very efficient it would be better to have some sort 
> of type.

V8 has been the exception, not the rule (no pun intended :-)) in
having very poor exception handling performance. Every other engine
has optimized them very well at this point. (Spidermonkey used to have
issues with functions that *threw* exceptions, but that's not as much
of a problem as it used to be, and it only deopt'ed once it actually
threw.)

In addition, V8's new interpreter/compiler pipeline, Ignition and
TurboFan, no longer has this issue, and can fully optimize code with
`try`/`catch` in it.

On Tue, Aug 22, 2017 at 3:46 PM, Mike Samuel  wrote:
>
>
> Noone's answered yet, so I'll take a stab.
>
> An instruction that completes normally transfers control to the "next"
> instruction analogous to incrementing the program counter.
>
> An instruction that returns pops (modulo yield) a stackframe which includes
> resetting the program counter to its state prior to the call, unless there
> are protected regions containing the program counter in which case it jumps
> to the innermost.  Protected regions in EcmaScript correspond to try{...}
> for the most part.
>



>
>>
>> 2. As previously stated a new type would probably be best since this can
>> be made much better then what is essentially a try/catch.
>> Since try catching is not very efficient it would be better to have some
>> sort of type. However, this leads to how to implement, it could just be a
>> class but then it could just be added manually. The real benefit to this
>> would be great integration with async/await and pattern matching
>
>
> Others are much more familiar with VM performance constraints, but IIRC, its
> not the catching that is inefficient, but associating the stackframe with
> the exception.
> Dispatching an exception within a stack frame just involves finding the
> innermost protected region containing the PC which is a binary search over a
> fairly small list of instruction indices.
> It sometimes matters whether you associate stack information with an Error
> on `new Error()` as in Java, or on throw as in Python but IIRC EcmaScript
> doesn't yet take a position on that.
> Throwing a non-Error-value also needn't incur the stack walk.
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>

-

Isiah Meadows
m...@isiahmeadows.com

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Strawman: `Function.prototype.try` (or `Function.try`)

2017-08-22 Thread Mike Samuel
On Tue, Aug 22, 2017 at 2:08 PM, Sebastian Malton 
wrote:

> 1. What is the difference between "normal" and "return"?
>

Noone's answered yet, so I'll take a stab.

An instruction that completes normally transfers control to the "next"
instruction analogous to incrementing the program counter.

An instruction that returns pops (modulo yield) a stackframe which includes
resetting the program counter to its state prior to the call, unless there
are protected regions containing the program counter in which case it jumps
to the innermost.  Protected regions in EcmaScript correspond to try{...}
for the most part.



> 2. As previously stated a new type would probably be best since this can
> be made much better then what is essentially a try/catch.
> Since try catching is not very efficient it would be better to have some
> sort of type. However, this leads to how to implement, it could just be a
> class but then it could just be added manually. The real benefit to this
> would be great integration with async/await and pattern matching
>

Others are much more familiar with VM performance constraints, but IIRC,
its not the catching that is inefficient, but associating the stackframe
with the exception.
Dispatching an exception within a stack frame just involves finding the
innermost protected region containing the PC which is a binary search over
a fairly small list of instruction indices.
It sometimes matters whether you associate stack information with an Error
on `new Error()` as in Java, or on throw as in Python but IIRC EcmaScript
doesn't yet take a position on that.
Throwing a non-Error-value also needn't incur the stack walk.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Strawman: `Function.prototype.try` (or `Function.try`)

2017-08-22 Thread dante federici
There exist lots of libraries that give this sort of functionality among
others in the functional community -- lots of Either or Maybe
implementations.

I don't think this is a healthy addition to the spec since you would then
want to consider all the other monadic goodies like mapping over these
values, folding, "all" and "some", etc.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Strawman: `Function.prototype.try` (or `Function.try`)

2017-08-22 Thread Sebastian Malton
  1. What is the difference between "normal" and "return"?2. As previously stated a new type would probably be best since this can be made much better then what is essentially a try/catch.Since try catching is not very efficient it would be better to have some sort of type. However, this leads to how to implement, it could just be a class but then it could just be added manually. The real benefit to this would be great integration with async/await and pattern matching    From: oriol-bugzi...@hotmail.comSent: August 22, 2017 6:23 PMTo: es-discuss@mozilla.orgSubject: Re: Strawman: `Function.prototype.try` (or `Function.try`)  
Instead of `thrown: false` or `thrown: false`, why not `type: "normal"`, `type: "return"` or `type: "throw"`? This is what completion records use.



-Oriol


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


Re: Strawman: `Function.prototype.try` (or `Function.try`)

2017-08-22 Thread Oriol _
Instead of `thrown: false` or `thrown: false`, why not `type: "normal"`, `type: 
"return"` or `type: "throw"`? This is what completion records use.

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


Re: Strawman: `Function.prototype.try` (or `Function.try`)

2017-08-22 Thread Jordan Harband
I think if we wanted to add a "Result" type, we might want to do that
holistically instead of having an arbitrary prototype method return an
arbitrary object literal.

It'd be really nice to have that type, but I'm not sure how easy it'd be to
make a compelling case.

On Tue, Aug 22, 2017 at 10:01 AM, Isiah Meadows 
wrote:

> Usually, it's most convenient to just let errors easily fall through,
> using `try`/`catch`/`finally`. But when you're writing more low-level
> error-handling code, especially where errors are never exceptional
> (like test errors in a testing framework or task errors in a
> distributed worker pool implementation), it's often easier to handle
> completions/results as if they were values, like how Lua [1] and Rust
> [2] handle it.
>
> [1]: https://www.lua.org/pil/8.4.html
> [2]: https://doc.rust-lang.org/book/second-edition/ch09-02-
> recoverable-errors-with-result.html
>
> Here's my proposal: introduce either `Function.try(func, thisArg,
> ...args)` or `Function.prototype.try(thisArg, ...args)`. It works much
> like `Function.prototype.call`, except instead of returning/throwing,
> it always returns a `{thrown, value}` pair.
>
> Polyfilling either would be easy:
>
> ```js
> Function.try = (func, thisArg, ...args) => {
> try {
> return {thrown: false, value: func.call(thisArg, ...args)}
> } catch (e) {
> return {thrown: true, value: e}
> }
> }
>
> Function.prototype.try = function (thisArg, ...args) {
> try {
> return {thrown: false, value: this.call(thisArg, ...args)}
> } catch (e) {
> return {thrown: true, value: e}
> }
> }
> ```
>
> Engines could make this much more performant, though, by detecting the
> function, avoiding the object allocation if immediately destructured,
> optimizing the arguments like `Function.prototype.call`, and if called
> with a lambda, inlining the whole thing into a pseudo-`try`/`catch`.
>
> -
>
> Isiah Meadows
> m...@isiahmeadows.com
>
> Looking for web consulting? Or a new website?
> Send me an email and we can get started.
> 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