Lee Byron (2015-02-25T00:56:54.000Z)
Thanks for this additional context, Brendan. The block lambda revival was particularly interesting to read up on. I understand why we went down the arrow function path, but it’s fun to think about what ES6+ might look like had we taken that different path.

I’d like to keep this proposal scoped specifically to reduce because I believe we already have adequate tools for the early exit of generic iteration with “for of / break/return", or at the very least, “forEach / throw”. Reduce is special member of the higher order functions in that most of the others list higher order functions can be implemented in terms of it, which is why they’re sometimes called “folds” or “reducers”.

Examples include

function map(fn, array) {
  return array.reduce((a, v) => a.concat([fn(v)]), []);
}

function filter(fn, array) {
  return array.reduce((a, v) => fn(v) ? a.concat([v]) : a, []);
}

However there are a bunch of higher order functions which can’t be implemented in terms of reduce without the ability to early exit: “takeN”, “takeWhile”, “takeUntil” are a few good examples of this case.

Could you implement these functions without reduce? Of course you can. But it would be nice to be able to leverage the reduce function for this purpose, especially when using JavaScript in a pure functional way.

A bit beyond the point of the proposal, but perhaps relevant is that @@reduced could be useful in user-land code as well. Example: Transducers is a newer concept that has a couple user-land libraries out there (here’s one http://cognitect-labs.github.io/transducers-js/classes/transducers.html) which extends the reducers concept. There’s some minor gymnastics done there to return and detect “reduced” values. Having a realm-shared well known symbol to represent this general concept would very likely be reused in libraries like these.

Lee


From: Brendan Eich <brendan at mozilla.org<mailto:brendan at mozilla.org>>
Reply-To: "brendan at mozilla.org<mailto:brendan at mozilla.org>" <brendan at mozilla.org<mailto:brendan at mozilla.org>>
Date: Monday, February 23, 2015 at 2:09 PM
To: "Mark S. Miller" <erights at google.com<mailto:erights at google.com>>
Cc: "es-discuss at mozilla.org<mailto:es-discuss at mozilla.org>" <es-discuss at mozilla.org<mailto:es-discuss at mozilla.org>>
Subject: Re: short-circuiting Array.prototype.reduce

Mark S. Miller wrote:
My other suspicion: The previous failure of this proposal was before many people had much hands on experience using higher order functions in JS as a normal alternative to control structures. Now that we all have, the need for a non-local escape may be more visceral.

Just in case anyone wants my historical two cents, I don't think this is true. I championed both

http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival

and

http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax

starting well after (spring 2011) the modern (Prototype.js, 2005?) higher-order function revival in JS.

Anyway, however much more momentum there is today compared to four years ago, we still don't have a clear winner. But we've been over this ground. I dug up some more links in a few minutes of site: googling.

Dave Herman proposed return to label here:

http://wiki.ecmascript.org/doku.php?id=strawman:return_to_label

This led to (among others):

https://esdiscuss.org/topic/march-24-meeting-notes#content-13

where Andreas Rossberg proposed `return from` to address the problem cited in this thread's o.p. His example used forEach, but no matter:


  function f(o) {
    o.forEach(function g(x) {
       if (...) return 0 from f;
       let x2 = x.map(function h(y) {
         if (...) return from g
         return y*2  // returns from h
       })
       ...
    })
    return 27
  }


/be
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150225/ad0d1698/attachment.html>
d at domenic.me (2015-03-06T00:51:29.262Z)
Thanks for this additional context, Brendan. The block lambda revival was particularly interesting to read up on. I understand why we went down the arrow function path, but it’s fun to think about what ES6+ might look like had we taken that different path.

I’d like to keep this proposal scoped specifically to reduce because I believe we already have adequate tools for the early exit of generic iteration with “for of / break/return", or at the very least, “forEach / throw”. Reduce is special member of the higher order functions in that most of the others list higher order functions can be implemented in terms of it, which is why they’re sometimes called “folds” or “reducers”.

Examples include

```js
function map(fn, array) {
  return array.reduce((a, v) => a.concat([fn(v)]), []);
}

function filter(fn, array) {
  return array.reduce((a, v) => fn(v) ? a.concat([v]) : a, []);
}
```

However there are a bunch of higher order functions which can’t be implemented in terms of reduce without the ability to early exit: “takeN”, “takeWhile”, “takeUntil” are a few good examples of this case.

Could you implement these functions without reduce? Of course you can. But it would be nice to be able to leverage the reduce function for this purpose, especially when using JavaScript in a pure functional way.

A bit beyond the point of the proposal, but perhaps relevant is that @@reduced could be useful in user-land code as well. Example: Transducers is a newer concept that has a couple user-land libraries out there (here’s one http://cognitect-labs.github.io/transducers-js/classes/transducers.html) which extends the reducers concept. There’s some minor gymnastics done there to return and detect “reduced” values. Having a realm-shared well known symbol to represent this general concept would very likely be reused in libraries like these.