質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1777閲覧

非同期処理以外でのgeneratorの使い道について

murabito

総合スコア108

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

2クリップ

投稿2018/04/01 15:27

編集2018/04/04 01:12

注釈

  1. KSwordOfHasteさんからの回答を拝見し、上手く初期の質問文が伝わっていない部分があったようなので質問文を一部修正、追記します。

  2. 他言語にもGeneratorがあるようなので、タグを追加させて頂きました。

質問

generatorの使い道というのは非同期処理を同期的っぽく書く時以外には、どんな使い道がありますか?

generatorの使い道をググるとたいてい出てくるのは非同期処理を同期的っぽく書くための手法が書かれた記事が大半な気がします。

でも、async awaitの登場によって、その用途であればgenerator使わなくても良くなりました。

以下、僕なりに認識しているgeneratorの特徴まとめです。

  1. 関数と違って途中で処理を中断出来、また再開できる
  2. iteratorと同様に、generatorも使う側が「くれ!」というと、その度にgeneratorが提供できる値が尽きるまで「どうぞ!」と使う側に渡してくれる
  3. next()の引数に値をgeneratorを使う側からgenerator側のyieldに渡すことで、generatorとやりとりができる
  4. generatorは他のgeneratorに処理を委譲できる

これらを踏まえた上で何に使えるのかなと考えては見るのですが、やはり用途が思いつきません。

何か非同期処理以外の用途でgeneratorって使い道はありますか?
こういう場面で使うと便利だよっていうようなケースがありましたら教えていただけると嬉しいです。

kakajika👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

defghi1977

2018/04/04 05:00

> 他言語にもGeneratorがあるようなので、タグを追加させて頂きました。 これでは回答が発散してまともな議論が出来なくなると思いますが?
murabito

2018/04/04 05:04

KSwordOfHasteもおっしゃっていた通り、本質は同じなのかなと思っていましたが異なりますでしょうか?
defghi1977

2018/04/04 05:11 編集

言語を跨いだ概念を知りたいのであれば、https://en.wikipedia.org/wiki/Generator_(computer_programming) 等を読むべきで、言語毎の応用にまで足を突っ込むと個人個人の解釈が足枷となって議論が混乱すること必至です(既にコメント合戦の様相を呈していますでしょう?).
murabito

2018/04/04 05:15

Because generators compute their yielded values only on demand, they are useful for representing streams, such as sequences that would be expensive or impossible to compute at once. These include e.g. infinite sequences and live data streams.
murabito

2018/04/04 05:20 編集

defghi1977さん、ご指摘ありがとうございました。wikiを見に行ったことで他の回答者さまからの回答も含め、いろんな点が繋がりました。
murabito

2018/04/04 05:20

質問を閉じたいと思いますが、ベストアンサーを選びづらいので少々お待ちくださいませ。
defghi1977

2018/04/04 05:22

とは言え質問自体は「ごもっとも」な内容で, 私もwikipediaを眺めて腑に落ちた点が多々あります.
guest

回答2

0

javascriptに限らずIteratorの仲間としてGeneratorをサポートした言語は他にもあります。なぜ同じ名前で呼ばれるかと言うともともと共通の概念を指すからだと思います。

Generatorは通常Iteratorの実装方法の一つとして捉えることができ、返すべき値をコルーチンとして書けるというのが本質的な特徴だと思います。

例としてPythonのrange(from, to)をJavascriptで書いてみますと・・・

Javascript

1 2// 普通の関数としてIteratorを実装した例 3 4function range(from, to) { 5 let r = {} 6 r[Symbol.iterator] = () => { 7 let i = from 8 return { 9 next() { 10 return i < to 11 ? { done: false, value: i++ } 12 : { done: true } 13 } 14 } 15 } 16 return r 17} 18 19// GeneratorとしてIteratorを実装した例 20 21function g_range(from, to) { 22 let r = {} 23 r[Symbol.iterator] = function* () { 24 for (let i = from; i < to; i++) { 25 yield i 26 } 27 } 28 return r 29} 30 31for (let i of range(1, 4)) { 32 console.log(i) 33} 34 35for (let i of g_range(1, 4)) { 36 console.log(i) 37}

1
2
3
1
2
3


上記を踏まえて元の質問に戻りますと・・・

1つ目は関数と違って途中で処理を中断出来、また再開できるということ

これをコルーチンといいます

2つ目は使う側が「くれ!」というと、その度にiteratorと同じように提供できる値が尽きるまで「どうぞ!」と渡してくれるということ、

これはgeneratorの特徴というよりIteratorの特徴です。

3つ目は、iteratorにはない特徴として、next()の引数に値をgenerator側に渡すことで、generatorとやりとりができるということかなと思います。

それは少々違うように思います。IteratorもGeneratorも「どのような列挙をしてほしいかを引数で指定するように実装できます」上記のrange, g_rangeが単純な例になっているかと思います。

何に使えるのかな

Iteratorを実装したい場面で複雑な場合分けなどを逐次処理的に書きたい場合はgeneratorとして記述した方が分かり易くなると言えます。それはコルーチンであるがゆえの特徴と言えるのではないでしょうか。

例えば1~3まで1おきに、次に10~30まで10おきの値を返すようなIteratorを定義してみますと

Javascript

1function it() { 2 let i = 1 3 return { 4 next() { 5 if (i < 4) 6 return { done: false, value: i++ } 7 if (i == 4) 8 i = 10 9 return i < 40 10 ? { done: false, value: i += 10 } 11 : { done: true } 12 } 13 } 14}

なんかnextの実装でやっている条件分岐がややこしいですよね。これをGeneratorでかくと非常に平易に書けます。

Javascript

1function* git() { 2 for (let i = 1; i < 4; i++) 3 yield i 4 for (let i = 10; i < 40; i += 10) 5 yield i 6}

単純な列挙をするなら普通の関数としてIteratorを実装してもGeneratorを使っても大差ない気がしますが、ちょっと複雑な列挙をしようとするときGeneratorの記述力の有用性が実感できるのではないでしょうか?

投稿2018/04/01 16:10

編集2018/04/04 02:07
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

murabito

2018/04/04 01:14 編集

具体的なコードつきて大変わかりやすい回答をいただきありがとうございました。イテレーターとジェネレーターの使い分けみたいなところがわかって良かったです。ありがとうございます。 > それは少々違うように思います。IteratorもGeneratorも「どのような列挙をしてほしいかを引数で指定するように実装できます」上記のrange, g_rangeが単純な例になっているかと思います。 generatorは使う側でgen.next('some value')とすることで、generator側のyieldから任意の値を渡すことが出来ますよね?iteratorだとそういうことって出来ないですよね。レス頂いた部分の意味としてはそういった意味合いでした。(わかりづらくてすみません) 他にも記載漏れがありましたがgeneratorは他のgeneratorに処理を委譲できるという特徴もあるので、それらをふまえてgeneratorでどんな便利な利用用途があるのかなという質問でした。 質問文を修正しましたので、もう少し回答を募集してみます。数日以内に回答がつかなければ質問を閉じたいと思います。
Lhankor_Mhy

2018/04/04 02:04

横からすみません。 murabito さん、用語の混乱が見られるようです。 murabito さんが考える(javascriptにおける)ジェネレータとは、次の内どれが近いですか? 1. ジェネレータ式|文 2. yield 文が含まれるオブジェクト全て 3. {done, value}のオブジェクトを返す next メソッドを持ったオブジェクト全て 4. Symbol.iterator プロパティの内、ネイティブコードではないもの全て もし、2であるなら、『iteratorだとそういうことって出来ないですよね』への回答は「3のやり方で記述できるのでそんなことないですよ」となります。
KSwordOfHaste

2018/04/04 02:51 編集

to:質問者さん Lhankor_Mhyさんがコメントくださった通りですが・・・ JavascriptのIterableやIteratorはアプリケーションプログラマーにとって「自分で定義するもの」という感覚ではないということなんだろうと思います。何かを列挙するという目的でIteratorを使うと考える場合、次のように考えるのが典型的だと思います。 (1)組み込みのIterable(ArrayとかStringとかBufferとかそういったもの)を利用する (2)そこから得られる(ライブラリー提供者が提供した実装済みの)Iteratorを利用する これに対してgeneratorはIteratorを直接自分で実装するものです。が、しかし実際はIterableもIteratorも自分で定義できます。その定義方法が若干トリックぽくなっている(Symbol.iteratorという特殊な属性を使う)ためGeneratorとは違って「自前で実装する」と捉えないのだろうと思います。確かに自分でこれを実装しようとは普通は考えませんね(w;)どこかのライブラリー提供者が実装したものを「使う」と考えるのが殆どでしょう。 つまり「(A)定義済みIterableを利用する」vs「(B)generatorを定義して利用する」みたいな感覚がアプリケーションプログラマーの普通の感覚だと思います。そういう意味でYouheiSakuraiさん回答もIterator vs Generatorの比較ではなく(A)vs(B)について述べておられるのだと思います。 質問文にはIterator vs Generator的な内容が含まれてたので自分はこれについて回答したのですが、よーく読んでみると列挙に限らずどういう使いかたができるかが質問意図だったということですかね。
murabito

2018/04/04 04:49

> Lhankor_Mhyさん ご指摘ありがとうございます。 確かに用語の整理が上手く出来ていなかったです。 > murabito さんが考える(javascriptにおける)ジェネレータとは、次の内どれが近いですか? こちら(`function*() {}`)のジェネレーター式の方です。 ジェネレーター関数が返すジェネレーターオブジェクトの方を、 質問文の中では"使う側"のような言葉にしてしまっていますね。 用語の整理が適切についておらずすみません。
murabito

2018/04/04 04:52

> Lhankor_Mhyさん 指摘を受け、質問文を推敲しようと思ったのですが、どういう言葉に置き換えて良いかわかりませんでした。
murabito

2018/04/04 05:02 編集

> Lhankor_Mhyさん 推敲してみました。まだ、おかしいですか? 正しく用語を認識出来ていないのか自信があまりないです。 generator式は関数式と違って途中で処理を中断、再開出来る iteratorオブジェクトと同様に、generatorオブジェクトも利用者が「くれ!」というと、その度にgeneratorオブジェクトが提供できる値が尽きるまで「どうぞ!」と利用者に渡してくれる generatorオブジェクトの利用者が、generatorオブジェクトが持つnextメソッドの引数に、任意の値を渡すことによって、generatorオブジェクトはその渡された値を現在のyield操作の返り値とすることが出来る。 generatorはgenerator式の中で他のgeneratorオブジェクトに処理を委譲できる https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Generator https://developer.mozilla.org/ja/docs/JavaScript/Reference/Operators/yield
murabito

2018/04/04 05:24

KSwordOfHasteさん、ご回答ありがとうございました。言語をまたいだgeneratorについて、また、JavaScriptにおいてのgeneratorの理解が非常に深まりました。
guest

0

ベストアンサー

私がGeneratorをよく使う理由の一番は、メモリに優しいからです。Generatorは値が必要になるまで何もしないので、すごく長いデータ列を返す関数でも都度都度必要な分のメモリしか使いません。ので、私は可変長のデータを返す関数を書くときには、ほとんどGeneratorにしてしまいます。そのほうが戻り値の長さが非常に長くなるケースを考えなくても良くなりますので。

例:fizzbuzz(n)

python

1def fizzbuzz(n): 2 '''1からnまでのFizzBuzz''' 3 for i in range(1, n + 1): 4 if i % 15 == 0: 5 yield 'FizzBuzz' 6 elif i % 3 == 0: 7 yield 'Fizz' 8 elif i % 5 == 0: 9 yield 'Buzz' 10 else: 11 yield i 12 13for word in fizzbuzz(1234567890): # どんなに大きな数字を渡してもメモリ使用量は上がらない 14 print(word)

投稿2018/04/04 01:44

YouheiSakurai

総合スコア6142

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

murabito

2018/04/04 05:05

PythonではGeneratorをよく使うという話は聞いたことがあって、Generatorのmotivationのところを読むと良いというアドバイスをスタックオーバーフローで見つけたのですが、長文英語で早々に挫折してしまいました。https://www.python.org/dev/peps/pep-0255/#motivation
murabito

2018/04/04 05:22 編集

やはり、pythonのようにビッグデータを扱うことが多い分野だからこそのGeneratorだったりするのでしょうか?JavaScriptでビッグデータを扱うことはないため、切り分けて考えた方が良いのでしょうか。(追記:こちらの疑問は自己解決いたしました)
murabito

2018/04/04 05:25

YouheiSakuraiさん、ご回答ありがとうございました。大変参考になりました。
YouheiSakurai

2018/04/04 05:26 編集

ビッグデータという訳では特になく、上手く表現できないんですがGeneratorを知ってからは、関数型プログラミングに寄った位置ではGeneratorを使わないとスマートに書けない場面に、いっぱい出くわすんです。私の例もGenerator無しには書けないですよね?で、こういうGeneratorにしておくとmapしたりfilterしたりも容易で便利なんです。
KSwordOfHaste

2018/04/04 05:26

自分はIteratorもGeneratorも同じですというようなトーンでコメントしたのですが、Iteratorを自前で定義するのは「Generatorのようにコルーチンとして逐次的に書けない」というのもさりながら、Iteratorプロトコル自体が低水準なため、「Iterableを使うとメモリー消費が多くなりがち」vs「Generatorを使うとメモリーを大量に消費せずに平易にIteratorが実装できる」と捉えた方がよく、YouheiSakuraiさんの回答が一番しっくりくるように思いました。
murabito

2018/04/04 05:27 編集

> YouheiSakuraiさん、 もしかして、generatorオブジェクトはイテラブルだから、mapやfilterに渡せるということでしょうか?
murabito

2018/04/04 05:29

> YouheiSakuraiさんの回答が一番しっくりくるように思いました。 ベストアンサーを移行させて頂きます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問