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

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

ただいまの
回答率

88.61%

KotlinのIntProgressionにはなぜparallel()が無いの?

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,246

mosa

score 214

いつもありがとうございます。
今、teratailの皆さんの助けを借りながらKotlinを勉強しています。

Kotlin の IntProgression は以下のような記述で便利だな、と思うのですが、
Java の parallel() のようなものがなくて不便だなと感じることがあります。

(1..100 step 2).forEach{ println(it) }

そこで、以下のような拡張関数を考えました。

fun IntProgression.stream() = IntStream.rangeClosed(first, last).filter{ (it - first) % step == 0 }
fun IntProgression.parallel() = stream().parallel()

こうすることで、以下のような記述ができます。

(1..100 step 2).parallel().forEach{ println(it) }

意図している動作はご理解いただけるかと思います。


 質問

こんなの元々組み込んであってもよさそうな気もするのですが、ないのは何かマズい点や理由があるからなのでしょうか。
IntProgression は iterator、IntStream は stream というのはわかるのですが、だからダメとはならないと思います。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

Kotlinのライブラリーインターフェースについて学び始めでしかないので間違ってたらすみません。

だからダメとはならないと思います

想像ですが「標準機能として提供するのは、慎重に考えないとインターフェース破綻の危険があるのではないか」と思います。

KotlinにはIterableとSequenceなどの独自インターフェースがありますね。IntProgressionはKotlin独自のIterableです。IterableがJavaと同様のインターフェースに見えるのになぜわざわざKotlin独自にしているかといえば、Kotlin Iterableがjavaのそれとは異なる機能を備えているからだと思います。例えばJavaではjava.util.stream.Streamでしかリッチなパイプライン機能(変換や集約といったもの)が使えません。一方、KotlinのIterableは拡張関数の力を借りてJavaのIterableよりずっと高機能になっていますね。要するに似てるけど別なインターフェースと言えましょう。

次に並列処理機能について考えると、JavaのStreamにあるparallelはKotlinには見当たりません。コルーチンがまだexperimentalですが、Kotlinはこれなどを用いてJavaとは違う戦略で並列処理機能を設計しようとしているような気がします。

以上から、「KotlinのIterableにJavaのStream固有のparallelを直接記述できるようにしてしまうとKotlinのIterableインターフェースが破たんしかねないのではないか」と想像しました。


余談:

ところで、Kotlin 1.1だと(1..2).asSequence().asStream()のようにするとStreamに変換できるようです。このように明示的に変換する分には混乱はないので一つの方法であるとは思います。

ただ・・・

(1..1000).asSequence().asStream().parallel().forEach(...)

という書き方を考えると、なんだか簡潔とは言い難いですし、それ以上にasStream()が効率よく並列動作できるようなSpliteratorを作ってくれるかが気になります。後者は並列処理のオーバーヘッド(※)にかかわります。その点がどうなっているか不明ですが、Stream#parallelを使うなら、最初からIntStream.rangeを使った方が素直だし安心な気がします。

※: オーバーヘッド
複数スレッド用にパイプラインを分割する際に、一旦上流のパイプラインから一定要素を取り出して配列として蓄積する段取りをふまないと並列動作を始められないことを指します。IntStream.rangeで生成されるIntStreamはこんな処理を必要とせず、S~EのストリームをS~S+PとS+P+1~Eの2つのストリームに即座に分割し並列動作を開始できます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/14 17:15

    ご回答ありがとうございます。
    わかりやすく記載していただき、理解できたのですが、
    「S~EのストリームをS~S+PとS+P+1~Eの2つのストリームに即座に分割し」のところが全くわからないため、この点、できればより具体的に教えていただくか、参考となるURLなどのご紹介などいただけませんでしょうか。

    キャンセル

  • 2017/10/14 17:33

    自分が参照したのはAPIリファレンス(のいささか抽象的な説明)およびIntStreamの内部実装です。

    Streamのパイプラインを制御するのはSpliteratorです。これはIteratorに似た動きをして、あるパイプラインが後段のパイプラインへ次に何を渡すかを制御しています。並列化の際にストリームをスレッドの数だけ分割するのはSpliteratorが担う機能なのですが、rangeの結果できるStreamのSpliteratorの実装は単純で、内部に現在値と終了値を覚えてるだけであり「次の値はなに?」と言われたとき「終了値に達してなければ現在値を返し(インクリメントし)、達していれば要素なしとする」みたいになってます。こういう実装ですから、分割位置を決めたとき、2つのSpliteratorに分割するには適当な内部状態に初期化された2つのSpliteratorを生成するだけで済みます。

    キャンセル

  • 2017/10/16 10:40

    初めて Stream や StreamSupport, Spliterator の実装を読んでみました。
    Java に関しても今まで Stream 関連は使い方の側面しかみていませんでした。
    ご回答頂いた内容を踏まえると、並列実行したいからといってIntProgressionである (1..100) を IntStream のシンタックスシュガーのように利用するのはあまり適切ではなさそうですね。
    引き続き勉強していきたいと思います。ありがとうございました。

    キャンセル

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

  • ただいまの回答率 88.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る