Inline generators do not work? (arrow-function) [duplicate] - javascript

That is, how do I express
function *(next) {}
with arrow syntax? I've tried all the combinations I could think of, and I can't find any documentation on it.
(I am currently using Node.js v0.11.14.)

Can I use ES6's arrow function syntax with generators?
You can't. Sorry.
According to MDN
The function* statement (function keyword followed by an asterisk) defines a generator function.
From a spec document (my emphasis):
The function syntax is extended to add an optional * token:
FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")"
"{" FunctionBody "}"

The difference between Inline-functions and Arrow-functions
First of all Arrow-functions () => {} are not made to replace Inline-functions function(){} and they are different.
Inline-Functions are simply Functions, so the question is what the difference between Arrow-functions and Inline-Functions are.
An arrow function expression (also known as arrow function) has a shorter syntax compared to function expressions and does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.
Some more quick details here
Why Arrow-function can not be used as generators
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Use of the yield keyword
The yield keyword may not be used in an arrow function's body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.
Note that generators without yield don't make sense.
Why Arrow-function can not use yield
http://tc39wiki.calculist.org/es6/arrow-functions/
Arrow functions bind this lexically, bind return in the Block body case so it returns from the immediately enclosing arrow function, and preclude break and continue from referencing statements outside the immediately enclosing arrow function.
The Identifier primary expression arguments may not be used in an arrow function's body (whether expression or block form).
Likewise, yield may not be used in an arrow function's body. Arrows cannot be generators and we do not want deep continuations.
Yield in an Arrow-Function will throw Semantic Error: http://www.ecma-international.org/
In the End the reason is in the deep complexity in the implementation of ECMA6. C# does not allow this as well for somewhat similar reasons.

In addition to the discussion on esdiscuss.org and the Ecma TC39 committee ES6 meeting notes from November 2013 mentioned above, generator arrows were revisited in two September 2016 ES7 meetings [1] [2]. After a discussion about pros and cons of various syntax (mainly =*> and =>*) and a lack of justifications and use cases for this feature, they came to the conclusion that:
There is some interest from the committee, but concern that the feature does not pull its weight for adding a new piece of syntax
Plan to revisit on Day 3 to see if we can get =>* to stage 0 at least, as part of [Domenic Denicola]'s async iteration proposal
The proposal for generator arrows was moved to Stage 1 with Brendan Eich and Domenic Denicola as champions. Asynchronous iteration mentioned above was finished and implemented in 2018.
In Oct 2019 an official repo by Sergey Rubanov appeared with more discussion about syntax and other details.

I was also having the same question and came here. After reading the posts and comments, I felt using generator in an arrow function seems to be vague:
const generator = () => 2*3; // * implies multiplication
// so, this would be a confusing
const generator = () =>* something; // err, multiplying?
const generator = () =*> ... // err, ^^
const generator = ()*=> ... // err, *=3, still multiplying?
const generator=*()=> ... // err, ^^
const generator = *param => ... //err, "param" is not fixed word
This is what may be the big reason they didn't implement generator in relation with arrow function.
But, if I were one of them, I could have thought like this:
const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^
This feels just like we have asynchronous function:
const asyncFunction = async () => ... // pretty cool
Because, with normal function the async keyword exist, so arrow function is utilizing it - async () => is likely to seem async function().
But, there's no keyword like gen or generator and alas arrow function is not using it.
To conclude:
Even if they wish to implement the generator in the arrow function, I think they need to re-think about generator syntax in core js:
generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}
And this will be a big blunder. So, keeping arrow function out from the generator, is pretty cool.
Following #Bergi comment:
No. Arrow functions are supposed to be light-weight (and don't have a .prototype for example) and often one-liners, while generators are pretty much the opposite.
I will say that generator purpose to use is run-stop-run and so I don't think we need to care about prototype, lexical this, etc.

Right now you can not, but in future you might be because TC39 release proposal for same in october 2019, which is in stage 1.

I know that this is very late, but another possible reason could be syntax. maybe (*() => {}) works, but what about (9 ** () => {})? Is that 9 to the power of an arrow function, returning NaN, or is it 9 times a generator arrow function, also returning NaN? It could be done with some alternative syntax, like =>* as mentioned by another answer here, but maybe there was a desire to preserve the consistency of the generator function syntax (eg. function* () {} and { *genMethod() {} }) when it was being implemented. Not too much of an excuse, but a reason for it.

You can, but not really in a nice way. It's not shorter and does not look that pretty. Check this out:
function* iterable(arg) {
yield* [];
}
async function* asyncIterable(arg) {
yield* [];
}
const arrowIterable = arg => {
return {
*[Symbol.iterator]() {
yield* [];
},
};
};
const arrowAsyncIterable = arg => {
return {
async *[Symbol.asyncIterator]() {
yield* [];
},
};
};
This works because an iterable is basically an object with the Symbol.iterator or Symbol.asyncIterator set to an iterator. A generator is an iterator!
Enjoy!

There is a nice workaround with redux-saga
import { call, all } from 'redux-saga/effects';
function* gen() {
yield all([].map(() => {
return call(....);
}));
}

Related

Why are Javascript Functions declared in different ways

Apologies if this seems like a beginner question, I am currently learning Javascript and have come across different ways of structuring function declarations. An example below
function mapStateToProps(state) {
console.log(state);
}
const mapStateToProps = state => {
console.log(state);
}
What is the benefit of using one or the other; in which situation would you use one over the other?
Arrow functions are the new ES2015 syntax, for me the main difference is changing this context you may read about it here https://medium.com/#thejasonfile/es5-functions-vs-es6-fat-arrow-functions-864033baa1a
The first example is a function declaration and the second example is a function expression. The second example you provided only serves to provide more concise JavaScript code to the first example and doesn't really capture the idea of your question of when to use ES6 arrow functions over function declarations. In other words your example, is just syntactic sugar, in your examples, nothing is really solved, just more concise code.
A better example is the following:
const team = {
members: ['Dolly', 'Billy'],
teamName: 'Hacking Crew',
teamSummary: function() {
return this.members.map(function(member) {
return `${member} is on team ${this.teamName}`;
});
}
};
console.log(team.teamSummary());
Run this snippet and you will see the error. Now, this error does not have to be solved with the arrow function, there are a couple of ways to solve it, but your question of in which situation would you use one over the other, this is a good use case for using an arrow function to solve this error.
Before I provide the solution, understand that fat arrow functions make use of what is called the lexical this. I will provide the refactor below and then unpack my previous sentence:
const team = {
members: ['Dolly', 'Billy'],
teamName: 'Hacking Crew',
teamSummary: function() {
return this.members.map((member) => {
return `${member} is on team ${this.teamName}`;
});
}
};
console.log(team.teamSummary());
Lexical means the placement of this term depends on how its interpreted or how its evaluated. So, depending on where we are placing the word this will change when using a fat arrow function.
When we use a fat arrow function and make reference to this inside of it this is automatically set equal to this in the surrounding context which in this code snippet is the team object.
So if lieu of using .bind(this) and having to cache a reference to this, you can replace fat arrow function as a solution.

Es6 Arrow function to normal js

I have been trying to understand es6 arrow function. I read some articles introducing it. But I'am still not getting it fully.
For example I have this code:
sortedArticles(): Article[] {
return this.articles.sort((a: Article, b: Article) => b.votes - a.votes);
}
It sorts the below array:
[
new Article('Angular 2', 'http://angular.io', 3),
new Article('Fullstack', 'http://fullstack.io', 2),
new Article('Angular Homepage', 'http://angular.io', 1),
];
How would the same code look in plain old js? I am not able to fully get it.
It would look like this if you just converted the arrow function to a function function:
sortedArticles(): Article[] {
return this.articles.sort(function(a: Article, b: Article) { return b.votes - a.votes;});
// ---------------------------^^^^^^^^------------------------^^^-------------------------^^
}
...but note that there's more going on there than ES2015 ("ES6"). The : Article[] part is saying that sortedArticles returns an array of Article. (And similarly the : Article qualifiers on a and b.) That's not JavaScript at all. It looks like TypeScript.
The pure JavaScript version would just drop those type annotations:
sortedArticles() {
return this.articles.sort(function(a, b) { return b.votes - a.votes;});
}
But TypeScript's "fat arrow" functions work largely the same way ES2015's arrow functions do, so let's continue on the basis that we're talking about ES2015 arrow functions:
There are four fundamental differences1 between arrow functions and function functions:
They close over this, super, and several other things,2 they don't have their own versions of those like function functions do. (A consequence of this is that they can use super if they're defined in a context that can use super, which function functions cannot.)
They can have a concise body rather than a verbose one (but they can have a verbose body as well).
They cannot be used as constructors. E.g., you can't use new with an arrow function. A consequence of this is that arrow functions don't have a prototype property on them (since it's only used if the function is used with new).
There is no generator syntax for arrow functions. E.g., there is no arrow equivalent to function *foo() { ... }.
These three functions are all effectively the same, since they don't use this or arguments:
// A `function` function
var f1 = function(x) {
return x * 2;
};
// An arrow function with a verbose body
var f2 = x => {
return x * 2;
};
// An arrow function with a concise body
var f3 = x => x * 2;
(If they used this or arguments, they would not be the same.)
Note that the concise body doesn't have a { after the => and must contain a single top-level expression (which can of course have subexpressions), which is used as the return value.
1 You'll find people telling you there's a fifth: That arrow functions cannot have a name. That's a myth. Arrow functions can have names; the arrow functions above have true names, f2 and f3 respectively. It's not just the variables that have names, the functions do as well.
2 Specifically, they close over this, super, arguments (the automatic pseudo-array of runtime arguments), and new.target.
A huge thank you to CodingIntrigue for pointing out several errors and omissions in the earlier versions of this answer.
If you're not familiar with arrow function, or if it's complicated, you can use JS Refactor, it's a Visual Studio Code extension. It can convert arrow function to normal function. Hope it helps someone.

Why does the Airbnb style guide say that relying on function name inference is discouraged?

// bad
class Listing extends React.Component {
render() {
return <div>{this.props.hello}</div>;
}
}
// bad (relying on function name inference is discouraged)
const Listing = ({ hello }) => (
<div>{hello}</div>
);
// good
function Listing({ hello }) {
return <div>{hello}</div>;
}
This is taken from the Airbnb react style guide. Can someone please explain why "relying on function name inference is discouraged"? Is it just a style concern?
I think this could also have something to do with the unexpected behaviour that you might run into from implicitly giving a lexical name to what you may expect to be an anonymous function.
Say for example someone understood the arrow function:
(x) => x+2;
To have the regular function equivalent:
function(x) {
return x+2;
}
It would be pretty easy to expect this code:
let foo = (x) => x+2;
To then be the equivalent of:
let foo = function(x) {
return x+2;
}
Where the function remains anonymous and would be incapable of referencing itself to do things like recursion.
So if then, in our blissful ignorance, we had something like this happening:
let foo = (x) => (x<2) ? foo(2) : "foo(1)? I should be a reference error";
console.log(foo(1));
It would successfully run because that function obviously wasn't anonymous:
let foo = function foo(x) {
return (x<2) ? foo(2) : "foo(1)? I should be a reference error";
}
This could potentially be exacerbated by the fact that in other situations where Babel implicitly adds a name to anonymous functions, (which I think is actually a bit of a side-effect of supporting implicit function names in the first place, though I could be wrong on that), they correctly handle any edge cases and throw reference errors where you would expect.
For example:
let foo = {
bar: function() {}
}
// Will surprisingly transpile to..
var foo = {
bar: function bar() {}
};
// But doing something like:
var foo = {
bar: function(x) {
return (x<2) ? bar(2) : 'Whats happening!?';
}
}
console.log(foo.bar(1));
// Will correctly cause a ReferenceError: bar is not defined
You can check 'view compiled' on this quick DEMO to see how Babel is actually transpiling that to maintain the behaviour of an anonymous function.
In short, being explicit with what you are doing is typically a good idea because you know exactly what to expect from your code. Discouraging the use of implicit function naming is likely a stylistic choice in support of this while also remaining concise and straightforward.
And probably hoisting. But hey, fun side trip.
EDIT #2: Found AirBnbs reason in their Javascript style guide
Don’t forget to name the expression - anonymous functions can make it harder to locate the problem in an Error's call stack (Discussion)
Original answer below
MDN has a good run-down on how function name inference works, including two warnings:
Observations
There is non-standard <function>.name inference behaviour in the following two scenarios:
when using script interpreters
The script interpreter will set a function's name property only if a function does not have an own property called name...
when using js tooling
Be careful when using Function.name and source code transformations such as those carried out by JavaScript compressors (minifiers) or obfuscators
....
In the uncompressed version the program runs into the truthy-branch and logs 'foo' is an instance of 'Foo' whereas in the compressed version it behaves differently and runs into the else-branch. Therefore, if you rely on Function.name like in the example above, make sure your build pipeline doesn't change function names or don't assume a function to have a particular name.
What is function name inference?
The name property returns the name of a function, or (before ES6 implementations) an empty string for anonymous functions
function doSomething() {}
console.log(doSomething.name); // logs "doSomething"
Functions created with the syntax new Function(...) or just Function(...) have their name property set to an empty string. In the following examples anonymous functions are created, so name returns an empty string
var f = function() {};
var object = {
someMethod: function() {}
};
console.log(f.name == ''); // true
console.log(object.someMethod.name == ''); // also true
Browsers that implement ES6 functions can infer the name of an anonymous function from its syntactic position. For example:
var f = function() {};
console.log(f.name); // "f"
Opinion
Personally I prefer (arrow) functions assigned to a variable for three basic reasons:
Firstly, I don't ever use function.name
Secondly, mixing lexical scope of named functions with assignment feels a little loose:
// This...
function Blah() {
//...
}
Blah.propTypes = {
thing: PropTypes.string
}
// ...is the same as...
Blah.propTypes = {
thing: PropTypes.string
}
function Blah() {
//...
}
// ALTERNATIVELY, here lexical-order is enforced
const Blah = () => {
//...
}
Blah.propTypes = {
thing: PropTypes.string
}
And thirdly, all things being equal, I prefer arrow functions:
communicate to reader that there is no this, no arguments etc
looks better (imho)
performance (last time I looked, arrow functions were marginally faster)
EDIT: Memory snapshots
I was listening to a Podcast and guest told of a situation were he had to deal with the limitations of using arrow functions with memory profiling, I have been in the exact same situation before.
Currently, memory snapshots will not include a variable name - so you might find yourself converting arrow functions to named functions just to hook up the memory profiler. My experience was quite straightforward, and I'm still happy with arrow functions.
Plus I've only used memory snapshots once, so I feel comfortable forgoing some "instrumention" for (subjective) clarity by default.
As any other style guide, Airbnb's is opinionated and isn't always well reasoned.
Function name property isn't supposed to be used for anything but debugging in client-side application because function original name is lost during minification. As for debugging, it becomes less efficient if a function doesn't have a meaningful name in call stack, so it's beneficial to preserve it in some cases.
A function gets name with both function definition like function Foo = () => {} and function named expression like an arrow in const Foo = () => {}. This it results in Foo function having a given name, Foo.name === 'Foo'.
Some transpilers follow the specification. Babel transpiles this code to ES5:
var Foo = function Foo() {};
And TypeScript breaks the specification:
var Foo = function () {};
This doesn't mean that named function expression is bad and should be discouraged. As long as a transpiler is spec-compliant or function name doesn't matter, this concern can be discarded.
The problem is applicable to transpiled applications. It depends on a transpiler in use and a necessity to keep function name property. The problem doesn't exist in native ES6.
This is because:
const Listing = ({ hello }) => (
<div>{hello}</div>
);
has an inferred name of Listing, while it looks like you are naming it, you actually aren't:
Example
// we know the first three ways already...
let func1 = function () {};
console.log(func1.name); // func1
const func2 = function () {};
console.log(func2.name); // func2
var func3 = function () {};
console.log(func3.name); // func3
what about this?
const bar = function baz() {
console.log(bar.name); // baz
console.log(baz.name); // baz
};
function qux() {
console.log(qux.name); // qux
}

Decorators on functions

I see that babel.js decorators (available in "stage 1") implement the spec at https://github.com/wycats/javascript-decorators. It appears that decorators are limited to (1) classes, (2) accessors, and (3) methods. In my case, I want to use decorators on plain old functions, as in
#chainable
function foo() { }
where (just an example)
function chainable(fn) {
return function() {
fn.apply(this, arguments);
return this;
};
}
I don't see any logical reason why decorators should not be able to apply to functions. My question is, is there some way to accomplish this? Or is there some good reason why functions cannot be decorated?
It turns out there is an issue raised for this at https://github.com/wycats/javascript-decorators/issues/4.
To execute a decorator, you evaluate an expression and doing that prevents hoisting (even for a variable declaration, the right-hand side of an assignment stays put). Therefore, it is not compatible with function declarations being hoisted.
As a work-around, I suggested that function expressions, generator function expressions and arrow functions could be enabled to be decorated:
const func = #someDecorator('abc') (x, y) => { return x + y };
Alas, that wasn’t met with much enthusiasm: Decorators for functions
You certainly have a point here.
But as neo_blackcap pointed out, function decorator are not part of the ES7 decorators draft.
So, the best thing you can do is to start discussion on the corresponding tracker to attract community attention to your proposal.
ES7 decorators are on their first stage of development second stage of development, meaning that their API is still under development and could undergo any change.
I think the problem is function decorator has not been ES7 draft.
Of course, you still can implement your function decorator by yourself

Can I use ES6's arrow function syntax with generators? (arrow notation)

That is, how do I express
function *(next) {}
with arrow syntax? I've tried all the combinations I could think of, and I can't find any documentation on it.
(I am currently using Node.js v0.11.14.)
Can I use ES6's arrow function syntax with generators?
You can't. Sorry.
According to MDN
The function* statement (function keyword followed by an asterisk) defines a generator function.
From a spec document (my emphasis):
The function syntax is extended to add an optional * token:
FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")"
"{" FunctionBody "}"
The difference between Inline-functions and Arrow-functions
First of all Arrow-functions () => {} are not made to replace Inline-functions function(){} and they are different.
Inline-Functions are simply Functions, so the question is what the difference between Arrow-functions and Inline-Functions are.
An arrow function expression (also known as arrow function) has a shorter syntax compared to function expressions and does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.
Some more quick details here
Why Arrow-function can not be used as generators
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Use of the yield keyword
The yield keyword may not be used in an arrow function's body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.
Note that generators without yield don't make sense.
Why Arrow-function can not use yield
http://tc39wiki.calculist.org/es6/arrow-functions/
Arrow functions bind this lexically, bind return in the Block body case so it returns from the immediately enclosing arrow function, and preclude break and continue from referencing statements outside the immediately enclosing arrow function.
The Identifier primary expression arguments may not be used in an arrow function's body (whether expression or block form).
Likewise, yield may not be used in an arrow function's body. Arrows cannot be generators and we do not want deep continuations.
Yield in an Arrow-Function will throw Semantic Error: http://www.ecma-international.org/
In the End the reason is in the deep complexity in the implementation of ECMA6. C# does not allow this as well for somewhat similar reasons.
In addition to the discussion on esdiscuss.org and the Ecma TC39 committee ES6 meeting notes from November 2013 mentioned above, generator arrows were revisited in two September 2016 ES7 meetings [1] [2]. After a discussion about pros and cons of various syntax (mainly =*> and =>*) and a lack of justifications and use cases for this feature, they came to the conclusion that:
There is some interest from the committee, but concern that the feature does not pull its weight for adding a new piece of syntax
Plan to revisit on Day 3 to see if we can get =>* to stage 0 at least, as part of [Domenic Denicola]'s async iteration proposal
The proposal for generator arrows was moved to Stage 1 with Brendan Eich and Domenic Denicola as champions. Asynchronous iteration mentioned above was finished and implemented in 2018.
In Oct 2019 an official repo by Sergey Rubanov appeared with more discussion about syntax and other details.
I was also having the same question and came here. After reading the posts and comments, I felt using generator in an arrow function seems to be vague:
const generator = () => 2*3; // * implies multiplication
// so, this would be a confusing
const generator = () =>* something; // err, multiplying?
const generator = () =*> ... // err, ^^
const generator = ()*=> ... // err, *=3, still multiplying?
const generator=*()=> ... // err, ^^
const generator = *param => ... //err, "param" is not fixed word
This is what may be the big reason they didn't implement generator in relation with arrow function.
But, if I were one of them, I could have thought like this:
const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^
This feels just like we have asynchronous function:
const asyncFunction = async () => ... // pretty cool
Because, with normal function the async keyword exist, so arrow function is utilizing it - async () => is likely to seem async function().
But, there's no keyword like gen or generator and alas arrow function is not using it.
To conclude:
Even if they wish to implement the generator in the arrow function, I think they need to re-think about generator syntax in core js:
generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}
And this will be a big blunder. So, keeping arrow function out from the generator, is pretty cool.
Following #Bergi comment:
No. Arrow functions are supposed to be light-weight (and don't have a .prototype for example) and often one-liners, while generators are pretty much the opposite.
I will say that generator purpose to use is run-stop-run and so I don't think we need to care about prototype, lexical this, etc.
Right now you can not, but in future you might be because TC39 release proposal for same in october 2019, which is in stage 1.
I know that this is very late, but another possible reason could be syntax. maybe (*() => {}) works, but what about (9 ** () => {})? Is that 9 to the power of an arrow function, returning NaN, or is it 9 times a generator arrow function, also returning NaN? It could be done with some alternative syntax, like =>* as mentioned by another answer here, but maybe there was a desire to preserve the consistency of the generator function syntax (eg. function* () {} and { *genMethod() {} }) when it was being implemented. Not too much of an excuse, but a reason for it.
You can, but not really in a nice way. It's not shorter and does not look that pretty. Check this out:
function* iterable(arg) {
yield* [];
}
async function* asyncIterable(arg) {
yield* [];
}
const arrowIterable = arg => {
return {
*[Symbol.iterator]() {
yield* [];
},
};
};
const arrowAsyncIterable = arg => {
return {
async *[Symbol.asyncIterator]() {
yield* [];
},
};
};
This works because an iterable is basically an object with the Symbol.iterator or Symbol.asyncIterator set to an iterator. A generator is an iterator!
Enjoy!
There is a nice workaround with redux-saga
import { call, all } from 'redux-saga/effects';
function* gen() {
yield all([].map(() => {
return call(....);
}));
}

Categories

Resources