super return
Well, there's already .map(), .find() and .filter() for returning values from arrays
An HTML attachment was scrubbed... URL: esdiscuss/attachments/20170828/3e3c5d7c/attachment-0001
On Mon, Aug 28, 2017 at 12:29 PM, Sebastian Malton <sebastian at malton.name> wrote:
I have seen some people want to modify some of the array prototype functions, especially forEach, so that returning from them returns a value. However, I have also seems that this could break things since in some cases, again forEach, the return value in explicitly defined.
Thus I propose the new syntax
super return
and any other positive number of supers. This syntax is currently not valid in any scenario and with the current meaning of super seems, to me at least, relativity easy to understand.The outcome of this basically means "return from current context up one level and then return from there".
A current method of doing this is by using try / catch but it is not ideal. Using the above method I believe that it would be able to be better optimized.
This has been suggested in the past, by adding a fourth argument to the callback signature passing an opaque "halt" value. Returning the halt value would end execution of the looping function prematurely. No reason to add new syntax for this, plus hooks for userland to take advantage of it, when we can just use something that userland could adopt today.
(As an added bonus, it would make the callback arguments be Element, Index, Collection, Halt, finally spelling out Brendan's full last name. ^_^)
This could be done but I see a few problems with it:
- Though it does make ending from some functions like forEach able to be done it does not all returning from other functions like map or sort
- It does not directly allow the returning of values but this might be rectified by having it be a function that you call and when it calls it stops any further calls and then returns the first parameter past
Original Message From: jackalmage at gmail.com Sent: August 28, 2017 4:17 PM To: sebastian at malton.name Cc: es-discuss at mozilla.org Subject: Re: super return
On Mon, Aug 28, 2017 at 12:29 PM, Sebastian Malton <sebastian at malton.name> wrote:
I have seen some people want to modify some of the array prototype functions, especially forEach, so that returning from them returns a value. However, I have also seems that this could break things since in some cases, again forEach, the return value in explicitly defined.
Thus I propose the new syntax
super return
and any other positive number of supers. This syntax is currently not valid in any scenario and with the current meaning of super seems, to me at least, relativity easy to understand.The outcome of this basically means "return from current context up one level and then return from there".
A current method of doing this is by using try / catch but it is not ideal. Using the above method I believe that it would be able to be better optimized.
This has been suggested in the past, by adding a fourth argument to the callback signature passing an opaque "halt" value. Returning the halt value would end execution of the looping function prematurely. No reason to add new syntax for this, plus hooks for userland to take advantage of it, when we can just use something that userland could adopt today.
(As an added bonus, it would make the callback arguments be Element, Index, Collection, Halt, finally spelling out Brendan's full last name. ^_^)
if (arr.find(e => typeof e != 'number')) throw new Error('...');
return arr.map(e => { if (!...) throw new Error(...); return e * 2; });
Odds are you need a conditional block, might as well be try catch.
On Mon, Aug 28, 2017 at 1:27 PM, Sebastian Malton <sebastian at malton.name> wrote:
This could be done but I see a few problems with it:
- Though it does make ending from some functions like forEach able to be done it does not all returning from other functions like map or sort
map() and forEach() have exactly the same signatures for their callbacks; you can definitely do the same thing in both of them.
You're right about sort(), but returning early from a sort() call
seems like a really small niche; I think it's the sort of thing you'll
only do in an error situation, in which case throwing is the correct
way to handle it. (On the other hand, returning early from a
forEach() can be due to perfectly normal reasons, the same sorts of
things that cause you to break
from a loop.)
- It does not directly allow the returning of values but this might be rectified by having it be a function that you call and when it calls it stops any further calls and then returns the first parameter past
It's the outer function's responsibility to return appropriate values. A map() call that didn't return an array would cause a lot of problems; a forEach call that returned something meaningful would be weird. In either case, it's a bad code smell to try and override what the outer function is doing. If you're stopping because of an error, and so whatever the function is trying to do isn't relevant anymore, you should throw an error instead.
Returning early should be implemented via a new takeWhile
call
On 28 August 2017 at 21:29, Sebastian Malton <sebastian at malton.name> wrote:
Thus I propose the new syntax
super return
and any other positive number of supers. This syntax is currently not valid in any scenario and with the current meaning of super seems, to me at least, relativity easy to understand.The outcome of this basically means "return from current context up one level and then return from there".
What if that context is no longer live? A function can outlive its creation scope. You could even try returning twice from the same function.
Allowing returns from outer functions has been discussed extensively in the ES6 phase (e.g. under the term "blocks"), but has been decided against in favour of arrow functions. One problem is that it introduces quite complex dynamic behaviour in general (it's halfway to introducing delimited continuations), and many new ways to fail.
A current method of doing this is by using try / catch but it is not ideal.
Using the above method I believe that it would be able to be better optimized.
That's unlikely, since it is just as dynamic in the general case (and the less general cases can be optimised equally well for both).
An HTML attachment was scrubbed... URL: esdiscuss/attachments/20170829/2931f49c/attachment
On 29 August 2017 at 14:30, Sebastian Malton <sebastian at malton.name> wrote:
If a function outlives its creation scope then this would do exactly what a normal return would do.
That makes no sense, because that's a completely different continuation, usually expecting different, unrelated types of results. It needs to be an error at least. (In a language with proper continuations the outer continuation would be captured by the inner closure and invoking it later would reestablish the execution context to return to. But TC39 always agreed that we don't want full-blown continuations in JS.)
On Aug 28, 2017, at 12:29 PM, Sebastian Malton <sebastian at malton.name> wrote:
The outcome of this basically means "return from current context up one level and then return from there”.
This would be a terrible violation of functional encapsulation. How do you know that the (e.g.) forOf function isn’t internally using a encapsulated helper function that is making the actual call to the call back. You simply have no way to predict where returning from the current context “up one” means.
A current method of doing this is by using try / catch but it is not ideal. Using the above method I believe that it would be able to be better optimized.
This technique provides a meaningful semantics because it allows the controlling outer function to define what early return means.
takeWhile
would work as follows:
myArray.takeWhile(element=>true) //Simplest case. Iterates over all
elements and returns a new array of them
It returns a new array with the consecutive elements from the start all of whose predicates returns truthy. Thusly it allows iteration with a custom exit condition, e.g.
myArray
.takeWhile(
element=>{
let condition
//calculate condition
return condition
}
)
Prior art: Java 9, rxjs, lodash and possibly others
Perhaps if the nested function is lexically inside such super function it can be fair game and actually quite powerful and liberating.
Unconstrained 'upleveling' is IIRC valid in such wonderful languages as Tcl. This unverified fact is presented without opinion :D
An HTML attachment was scrubbed... URL: esdiscuss/attachments/20170830/917682d7/attachment-0001
On 08/29/2017 08:56 AM, Allen Wirfs-Brock wrote:
On Aug 28, 2017, at 12:29 PM, Sebastian Malton <sebastian at malton.name <mailto:sebastian at malton.name>> wrote:
The outcome of this basically means "return from current context up one level and then return from there”.
This would be a terrible violation of functional encapsulation. How do you know that the (e.g.) forOf function isn’t internally using a encapsulated helper function that is making the actual call to the call back. You simply have no way to predict where returning from the current context “up one” means.
I agree. I think this would be much better as
function someThing(doWith) {
return doWith.map(elem => {
typeCheckLabel:
return elem * 2;
});
come from typeCheckLabel if (typeof elem !== "number");
return "Not all are numbers" ;
}
:-)
(I agree with the encapsulation argument.)
An HTML attachment was scrubbed... URL: esdiscuss/attachments/20170828/cbb63387/attachment