# ダイジェスト版 『コルーチン』とはなんだったのか
2019/05/30
『n月刊ラムダノート』創刊記念パーティー
https://hackmd.io/p/S1dw4Xy2V#/
https://hackmd.io/0j1gPlznSo6JBO0MloITfA#
---
## 自己紹介
* 遠藤侑介 @mametter
* クックパッドで働くフルタイム Ruby コミッタ
* Ruby 3 の静的検証とかテストまわりとか
* コルーチンは Ruby コミッタになったきっかけ(の 1 つ)
---
## \[ruby-dev:30827\]
ささだ 2007/05/28
> Continuation のついでに Fiber を入れました。
> (略)
> というわけで、皆様にいくつかご相談です。おもに、名前と機能の話です。広くご意見を頂けると幸いです。
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/30827
---
## \[ruby-dev:31596\]
遠藤 2007/08/22
> Fiber や Coroutine という言葉には、ちゃんとした定義もコンセンサスもないようなので、はっきりいって言ったもん勝ちです。
> (略)
> 短くてかっこいいのを選べばいいと思います。
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/31596
---
## コルーチンとは
* 伝統的コルーチン(2000年代まで)
* なんか制御構造みたいなやつ
* 2 種類ある
<!-- .element: class="fragment" data-fragment-index="1" -->
* async function のこと(2010年代から)
* 非同期処理を楽に書くやつ
* 伝統的コルーチンとは完全に別物
<!-- .element: class="fragment" data-fragment-index="2" -->
---
## 対称コルーチン
元祖のコルーチン、`transfer` で実行を渡す
```ruby
A = Fiber.new {
# 2. A に実行が渡された → B に実行を渡す
B.transfer()
# 4. A に(再度)実行が渡された → 実行終了
}
B = Fiber.new {
# 3. B に実行が渡された → A に実行を返す
A.transfer()
# ここには到達しない
}
# 1. コルーチン A に実行を渡す
A.transfer()
```
単純だけど使いにくいので使われていない
<!-- .element: class="fragment" data-fragment-index="1" -->
---
## 非対称コルーチン
resume で起動(再開)、yield で中断
```ruby
A = Fiber.new {
# 2. A が起動された → 中断して呼び出し元に処理を返す
Fiber.yield()
# 4. A はここから再開する → 終了して呼び出し元に処理を返す
}
# 1. コルーチン A を起動する
A.resume()
# 3. A が中断して帰ってきた → A を再開する
A.resume()
# 5. A が終了して帰ってきた → 実行終了
```
2000年代まではコルーチンと言えばコレだった
<!-- .element: class="fragment" data-fragment-index="1" -->
無限列の実装に使える
<!-- .element: class="fragment" data-fragment-index="2" -->
---
## async function
async/await: 非同期処理を同期風に書く記法
```javascript
async function asyncABC() {
await sleep(1000);
print("foo");
await sleep(1000);
print("bar");
}
await sleep(1000);
print("baz");
```
ここでの「コルーチン」=`async function`
<!-- .element: class="fragment" data-fragment-index="1" -->
<span><!-- .element: class="fragment highlight-red" -->**伝統的コルーチンとは完全に別物!**</span>
<!-- .element: class="fragment" data-fragment-index="2" -->
---
## 背景:JSの歴史的経緯 (1/4)
1990年代:関数は即時リターンする文化
* イベントを待つならコールバックを登録する
* ~~主な用途:いたずら、ブラクラ~~
* みんな JS オフにしてた
---
## 背景:JSの歴史的経緯 (2/4)
2000年代:JavaScript アプリの複雑化
* Ajax, prototype.js, jQuery
* 『コールバック地獄』の発生
* インデントが無限に深まっていく
---
## 背景:JSの歴史的経緯 (3/4)
ES2015:非対称コルーチンと Promise の導入
* コールバック地獄を(理論上は)解決
* でも実際にはまだまだ書くのダルい
* JS 民「非同期処理はコルーチンで!」
---
## 背景:JSの歴史的経緯 (4/4)
ES2017:async/await の導入
* わりとシンプルに書けるようになった
* JS 界に平和が訪れた (?)
* しかし……
---
## あらたな用語地獄
* JavaScript コミュニティの一部でコルーチンと async function がやや混同されている
* async/await を輸入した Python は async function を「コルーチン」と呼んだ
* Kotlin は伝統的コルーチンも async function もまとめて「コルーチン」と呼んだ
すでに別の意味で定着しつつある模様
---
## まとめ
みんなが愛した伝統的「コルーチン」は死んだ
* 背景や文脈によって意味が異なる
* 齟齬が生じないように注意しましょう
{"metaMigratedAt":"2023-06-14T21:35:18.209Z","metaMigratedFrom":"YAML","title":"ダイジェスト版「コルーチン」とは何だったのか","breaks":true,"description":"『n月刊ラムダノート』創刊記念パーティーでの発表資料","contributors":"[{\"id\":\"c3507607-74d8-4144-9c70-0cc97a728682\",\"add\":6871,\"del\":3907}]"}