アンチネスト構文
↓これ途中で概念がごっちゃになってて、以下は区別すべき
a) 単純にネストを減らすもの
JSのawait、Kokaのwith
b) 各行を関数呼び出しに変換するもの
Haskellのdo、Scalaのfor
----
Haskellのdo、Scalaのfor、F#のコンピュテーション式みたいなものを入れたらどうか
「みたいなもの」とは
手続き型っぽい記法が、関数呼び出しのチェーンに展開される記法
いろんな用途に使える
いろんな用途とは
Resultをまとめる (Rustでいう? )
async-await
Haskellのdo
Scalaのfor
map, flatMapとかに展開される
(2022-06追記) Kokaのwith
with以降、関数末尾までがクロージャになる
検討事項
目印をどうするか (do for のようにキーワードにするのか、しないのか)
code:shiika
# --- Array
result = for {
x * y
}
# 変換後
result = 1,2,3.flat_map{|x| x * y
}
}
# --- Maybe
for {
name <- user.name
book <- Book.find_first_by_author(name: name)
book.title
}
# 変換後
user.name.flat_map{|name| # nameがNoneのときはブロックを実行せずNoneを返す
Book.find_first_by_author(name: name).map{|book| # bookがNoneのときはブロックを実行せずNoneを返す
book.title # bookがSomeのときは中身をyieldしてSomeを返す
}
}
# --- Result
for {
x <- task1
task2
task3(x)
}
# 変換後
task1().flat_map{|x| # task1の結果がErrのときはブロックを実行せずErrを返す
task2().map{||
task3(x)
}
}
# --- 非同期
task = for {
x <- get_from_network
y <- heavy_processing(x)
send_and_wait(y)
}
task.run
# 変換後
get_from_network.flat_map{|x|
heavy_processing(x).map{|y|
send_and_wait(y)
}
}
メモ
scalaだとforeachに展開されるものがあるらしい
全部map/flat_mapにしてしまうと巨大な配列ができて困ることがあるだろうか?
モナドには高階多相が必要?
F#のコンピュテーション式はモナドが実装できるが、F#に高階多相はない
これは朗報
SwiftのFunction Builderが似てる?
2022-06
await、yieldってperformで書けるのかな