F# Asyncに関しての落書き その1

調べてる最中の落書きなので、指摘ある場合はどんどんお願いします。

コードを読むための前提知識(たぶん)

  • .NETの非同期
  • 継続
  • Trampoline

ソースコード

今読んでるやつ

https://github.com/fsharp/fsharp/blob/6ac6318858da25fe4f1d4728901c5824e9f3bf3a/src/fsharp/FSharp.Core/control.fs

FakeUnitValue

https://github.com/fsharp/fsharp/blob/6ac6318858da25fe4f1d4728901c5824e9f3bf3a/src/fsharp/FSharp.Core/control.fs#L383

ここはコメントの通り、と。

Trampoline

内部でのAsync専用Trampolineの実装に.NETの限界を垣間見る

do!とか

Async in C# and F#: Asynchronous gotchas in C# (Japanese translation) に"末尾再帰関数では do! より return! を使うべき"とか書いてあった気がする。do! の変換を見てみよう。

詳説コンピュテーション式 - ぐるぐる~

上記でも解説されている通り、do!には二つの変換パターンが存在する。

T(do! e in ce, C) = T(let! () = e      in ce,         C)
T(do! e;,      C) = T(let! () = src(e) in b.Return(), C)

末尾再帰関数として使う場合に使うのは後者。Bindが適用されてからReturnする影響でリークする可能性があるのかな?(実装を全部読む時間が足りない…)まぁ、無駄な呼び出しはしないほうが良いのは確かだ。

Asyncとは関係ないが、let!でもSource適用するのになんでdo!にもつけたのだろう。それも片方の変換だけ…

Async.Catch

コンピュテーション式内でtry withを使うのとAsync.Catchで包むの、どちらが良いのだろう?え、Choice使いたくない?まぁ、はい。

overload

https://github.com/fsharp/fsharp/blob/1745b5f7b19bdb285f3a9c06527b22baf01d41f9/tests/fsharp/typecheck/sigs/pos12.fs

テストで思い切りビルダーに対して拡張メソッドを定義している…わりとよくやるのだろうか。というか、F# 3.0以降なら

type Microsoft.FSharp.Control.AsyncBuilder with
    member x.Source(computation:Task<'T>) = Async.AwaitTask computation

でいいのでは感。どうせなら次のバージョンで標準搭載されてほしい。


会社に遅刻するので、今日はここまで。