ES6のアロー関数構文をジェネレーターで使用できますか?(矢印表記)


242

つまり、これをどのように表現すればよいですか。

function *(next) {}

矢印付き。私は考えられるすべての組み合わせを試しましたが、それに関するドキュメントは見つかりません。

(現在ノードv0.11.14を使用)


5
できません。ごめんなさい。「function*ステートメント(アスタリスクが後に続く関数キーワード)は、ジェネレーター関数を定義します。」

2
esdiscuss.orgでこのトピックに関するやや長い議論があったことに注意してください。
voithos 2014

4
何をするparam*=>{ }つもりですか?
CoderPi

4
あなたはそれfunction(){}が同じことをしていないことを知ってい()=>{}ますか?
CoderPi

8
それは本当にES6ジェネレーターが2ステップ前進し、1ステップ後退することですか?」-いいえ、ジェネレーターは前進することしかできません:-)
Bergi

回答:


230

ES6のアロー関数構文をジェネレーターで使用できますか?

できません。ごめんなさい。

MDNによると

function*声明(functionアスタリスクが続くキーワード)はジェネレータ関数を定義します。

仕様ドキュメントから(私の強調):

関数の構文は、オプション追加するように拡張された*トークンを:

FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")" 
  "{" FunctionBody "}"

174
私には設計上の欠陥のように感じます。
Jonathon 2015

23
@Jonathon:いいえ。アロー関数は軽量で(.prototypeたとえば、ない)、多くの場合は1行であると想定されていますが、ジェネレーターはほとんど逆です。
Bergi

38
私はすでにいくつかのシナリオで実行していて、私が遊んでいたジェネレーターが以前のへのアクセスが必要であり、ジェネレーター内でそれにアクセスするためにハックをthis作成する必要がありましたlet self = this。字句スコープ+矢印構文は良かったでしょう。残念ながら、世界の終わりではありません。
dvlsg


20
@Bergiの矢印関数の背後にある推論は、それよりもはるかに複雑です。それは本当に簡潔さについてではありません。アロー関数は軽量である必要はありません。オプションの単一ステートメント本文構文があるのは事実ですが、それは何ですか。多くの人は、クラスメソッドを除くすべての関数定義に矢印を使用し、functionキーワードを言語の「悪い部分」に降格させます。これには正当な理由があります。これらの人々にとって、矢印ジェネレーターの欠如は厄介な矛盾です。
カラム2017

130

インライン関数とアロー関数の違い

まず第一に、アロー関数 () => {}はインライン関数に取って代わるものではなくfunction(){}、それらは異なります。インライン関数は単に関数なので、問題はアロー関数とインライン関数の違いは何ですか。

(また、矢印機能として知られている)、矢印関数式は、関数式に比べて短い構文を持ち、独自に結合しないthisargumentssuper、またはnew.target)。アロー関数は常に匿名です。

詳細はこちら


アロー関数がジェネレーターとして使用できない理由

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

yieldキーワードの使用

収量キーワードは(さらにその中にネストされた関数内で許可する場合を除いて)矢印関数の本体で使用されなくてもよいです。結果として、矢印関数はジェネレーターとして使用できません。

を持たないジェネレータyieldは意味をなさないことに注意してください。


アロー関数がyieldを使用できない理由

http://tc39wiki.calculist.org/es6/arrow-functions/

矢印関数はthis字句的にバインドreturnし、ブロック本体のケースにバインドして、直接囲んでいる矢印関数から戻り、直接囲んでいる矢印関数の外側のステートメントを除外breakおよびcontinue参照します。

識別子の一次式は、arguments矢印関数の本体(か発現またはブロック形)で使用されなくてもよいです。

同様yieldに、アロー関数の本体では使用できません。矢をジェネレータにすることはできませんし、私たちは深い継続を望んでいません。

Arrow-FunctionのYieldはセマンティックエラーをスローしますhttp : //www.ecma-international.org/

結局のところ、理由はECMA6の実装における深い複雑さにあります。C#でもこれと同じような理由でこれを許可していません。


3
私は検索エンジンを使用してもう1つの説明を投稿しました
CoderPi

1
についての説明を追加()=>{}すると、インライン関数との違い、およびジェネレーターに制限がある理由を理解するのに非常に役立つと私はまだ思います。
vitaly-t 2015

63
私はなぜ*() => { yield bla; }大丈夫ではないのかを理解しようとしていますasync () => { await bla; }が、それは...
リーベンソン

7
@CodeiSir、Re " そして、私たちは深い継続を望んでいません "、お粗末な言い訳。
Pacerier 2017年

9
あなたの議論は循環的です。アロー関数は、yieldキーワードを含めることができないため、ジェネレーターにはなれません。ただし、ジェネレーターになることはできないため、yieldキーワードを指定することはできません。「矢印はジェネレーターにすることはできず、深い継続は必要ありません。」
Thayne

35

上記の2013年11月のesdiscuss.orgEcma TC39委員会のES6会議ノートに関する議論に加えて、ジェネレーターアローが2016年9月の2回のES7会議で再検討されました[1] [2]。さまざまな構文(主に=*>および=>*)の長所と短所、およびこの機能の正当化と使用例の欠如について話し合った後、次の結論に達しました。

  • 委員会からいくらか関心がありますが、この機能が新しい構文を追加するための重さを引き出していないことに懸念があります。
  • =>*[Domenic Denicola]の非同期反復提案の一部として、少なくともステージ0に到達できるかどうかを確認するために、3日目に再訪問することを計画します。

ジェネレーターアローの提案は、ブレンダンアイヒとドメニックデニコラをチャンピオンとしてステージ1に移動しました。上記の非同期イテレーションは2018年に完成し、実装されました。

2019年10月、Sergey Rubanovによる公式リポジトリが登場し、構文やその他の詳細についてさらに議論が行われました。


8

私も同じ質問をしていて、ここに来ました。投稿とコメントを読んだ後、私はarrow関数でジェネレーターを使用することは曖昧に思われます:

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

これが、アロー関数に関連してジェネレータを実装しなかった大きな理由かもしれません。


しかし、私がその1人だったとしたら、次のように考えることができたでしょう。

const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^

これは、非同期関数があるように感じます。

const asyncFunction = async () => ... // pretty cool

なぜなら、通常の機能ではasyncキーワードが存在するため、矢印機能がそれを利用しasync () =>ているように見えるからですasync function()

しかし、genorのようなキーワードgeneratorはなく、残念ながらアロー関数はそれを使用していません。

結論として:

アロー関数にジェネレーターを実装したい場合でも、コアjsのジェネレーター構文について再考する必要があると思います。

generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}

そして、これは大きな失敗です。したがって、矢印関数をジェネレーターから遠ざけることは、かなりクールです。


@Bergiのコメントに続いて:

いいえ。アロー関数は軽量で(たとえば、.prototypeがない)、多くの場合1行であると想定されていますが、ジェネレーターはほとんど逆です。

使用するジェネレーターの目的はrun-stop-runであると言いますので、プロトタイプやレキシカルなthisなどを気にする必要はないと思います。


2
のようなエキゾチックなオプションも検討できます() ~> { yield 'a'; yield 'b'; }。正直なところ、チルダが大好きです。
Gershom

@Gershomこれは、Perlのようなプログラミング言語が完全にうまくいかない方法です
Sapphire_Brick

2

これは非常に遅いことはわかっていますが、もう1つの考えられる理由は構文です。多分(*() => {})動作しますが、どう(9 ** () => {})ですか?これは、9のアロー関数の累乗でNaN戻りNaNますか、それとも9倍のジェネレーターアロー関数で戻りますか?=>*ここで別の回答で述べたように、これはいくつかの代替構文で行うことができますが、ジェネレーター関数構文(function* () {}およびなど{ *genMethod() {} })の実装時に一貫性を維持したいという要望があったかもしれません。言い訳はあまりしませんが、理由はあります。


1
:+1:アスタリスクが2つある場合...古い学校のJS男性 古い犬に新しいトリックを教えることはできないと言う人:joy:
シャニマル

彼らがそれをしない唯一の理由は、パーサーを作ることが難しいからです。それは完全に可能であり、構文の妥協は必要ありません。
Jason McCarrell

@JasonMcCarrellパーサーが複雑になりすぎないように十分に気を配っている場合は、Brendan EichがブラウザにSchemeを配置しているはずです。
Sapphire_Brick

1

現時点ではできませんが、将来的には、ステージ39にあるTC39が2019年10月に同じものをリリースするためと考えられます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.