25
continuatioN L inking 2016.04.16 NL-NAGOYA 2016 KOUJI MATSUI (@KEKYO2)

continuatioN Linking

Embed Size (px)

Citation preview

continuatioNLinking2016.04.16 NL-NAGOYA 2016 KOUJI MATSUI (@KEKYO2)

自己紹介

けきょ (@kekyo2, www.kekyo.net)

ロードバイク乗り

Microsoft MVP for Visual Studio and Development Technology

認定スクラムマスター・スクラムプロダクトオーナー

Center CLRオーガナイザー

最近

というか、かなり昔から「継続」に興味がありまして。◦ブログに連載を始めました

※注: 学問的厳密性は無いです

アジェンダ

CPS (継続渡しスタイル / Continuation Passing Style)

.NET Task / async-await / F# Async workflow

Continuation Linking

キーワード: Continuation Passing Style「継続渡しスタイル」◦ 継続渡しスタイル (CPS: Continuation-passing style) とは、プログラムの制御を継続を用いて陽に表すプログラミングスタイルのことである。(Wikipedia)

何だ、名古屋的ヤヴァイやつか。

… 陽に表す、とは

Continuation Passing Style

処理の完了時に、次に実行すべき処理を渡させる

継続させる処理を関数(ラムダ式)でネストさせて渡していく

一般的な逐次処理

Continuation Passing Style

「継続渡し (Continuation Passing)」

継続させる処理≒コールバック

Continuation Passing Style

コールバックで処理を継続させるといえば、JavaScriptのコールバックハンドラーとかメジャーですね。

「継続渡し (Continuation Passing)」

難しくない!!「CPS」という名前を付けただけだ!

Continuation Passing Style

CPSについてわかりましたか?

これが何?という疑問は「沼」なので、ここではスルーします。◦各自、ググって下さい。

「継続渡し」というものが感覚的に分かればよいです。

アジェンダ

CPS (継続渡しスタイル / Continuation Passing Style)

.NET Task / async-await / F# Async workflow

Continuation Linking

キーワード: .NET Task

.NET 4.0から導入された、「タスク」を透過的に扱うクラス。

更に、.NET 4.5とC# 5.0のasync-awaitを使って、非同期処理をタスクとして扱えるようにした。

CPSと何の関係が?

.NET Task (.NET 4.0 / C# 4.0)

まずは、.NET 4.0 TaskのCPS (ContinueWithを使う)

関数に直接継続を渡していないが、Task.ContinueWithに継続を渡している≒ CPS

注: 手を抜いてasync使ってます

.NET Task (.NET 4.5/C# 5.0)

そして、.NET 4.5/C# 5.0 でのasync-awaitによる非同期処理

これが「継続」だと分かりますか?

async-awaitでもTaskを使う

.NET Task comparison

つまり、async-awaitによるTaskの継続も、「構文糖」と見なせば一種のCPSです。

…たぶん

これが .NET 4.0 (C# 4.0 Task only) こうなる .NET 4.5 (C# 5.0 async-await)

キーワード: F# Async workflow

F# 2.0から導入された「非同期ワークフロー」。

非同期処理をシームレスにF#構文に統合(.NET 2.0以降)

CPSと何の関係が?

F# Async workflow

ほとんどasync-awaitと一緒これが「継続」だと分かりますか?

返されるのは Async<int>

※ let! (Let-Bang) は、Async<T>を非同期処理として待機して、結果のTを束縛します。C#でのawaitに相当。

※ F# Async workflowのCPSは長いので省略。Async.FromContinuations<T>関数を使います。

非同期継続のまとめ

.NET Task : ContinueWith

.NET Task : async-await

F# Async workflow : let!

それぞれの非同期処理の継続手段が、暗に「CPS」であることがわかりましたか?

アジェンダ

CPS (継続渡しスタイル / Continuation Passing Style)

.NET Task / async-await / F# Async workflow

Continuation Linking

「継続」を「接続」する

.NET TaskとF# Asyncをシームレスに接続して、相互運用可能にできたらいいね。◦大枠において対比出来る、Task<T> ⇔ Async<T>という関係から妄想

つまり:◦ F# AsyncをC#側でawait出来たらいいよね?

◦ .NET TaskをF# Async workflowでlet!出来たらいいよね?◦ HttpClient.GetStreamAsync()とか、普通にuse!できるようになるよ。

.NET Task / C#側のシナリオ

Async<T>クラスに対して拡張メソッドを定義して「AsTaskメソッド」を生やし、 Async<T> →Task<T>に変換可能にする。◦ Async.StartWithContinuations<T>関数を使って、TaskCompletionSource<T>を操作(SetResult・SetException・SetCanceled)し、Task<T>クラスを返す。

Async<T>クラスに対して拡張メソッドを定義して「GetAwaiterメソッド」を生やす。◦ C# でAsync<T>に対して直接awaitが可能になる。

※ F#のAsync<T>クラスは、正確にはFSharpAsync<‘T>クラスです。

.NET Task / C#側のシナリオ

Async<int>を直接awaitで待機(GetAwaiterが呼ばれる)

F# Async workflow側のシナリオ

Asyncクラスに対して拡張関数を定義して「AsAsync関数」を生やし、Task<T>→Async<T>に変換可能にする。◦ Async.FromContinuations<T>関数を使って、Task.ContinueWithメソッドのコールバックからAsync<T>の継続を操作する。

AsyncBuilder<T>クラスに対して拡張関数を定義して「Source関数」を生やす。◦ Source関数がTask<T>を受け取りAsync<T>に変換することで、F# Async

workflow内で直接let!が可能になる。

※ let!の他にdo!・return!・use!もありますが、Source関数を定義することでこれらすべてに対応できます。

F# Async workflow側のシナリオ

Task<int>を直接let!で待機(Sourceが呼ばれる)

こまごまとしたシナリオSystem.VoidとFSharp.Unitの、型安全な変換の考慮◦ Async<unit>をawaitすると、戻り値を受け取れないようにする。◦ Task(非ジェネリック)は、do!しかできないようにする。

CancellationTokenのサポート◦ F#側はAsync workflowのコンテキスト中で共通に割り当てられるTokenが存在するが、Task側にはそのような概念はない。

◦ AsTask/AsAsyncで変換する際に、明示的に渡せるようにする。

Async.RunSynchronous関数を使わない◦ 使ったらハードブロックしてしまう。Task.Waitメソッドを呼び出すことに該当。FromContinuations<T>やStartWithContinuations<T>を使う。

AsyncCompletionSource<T>を作る◦ FromContinuations<T>はコールバック関数を基礎としているので扱いにくい。

TaskCompletionSource<T>に相当する、F# Asyncの委譲クラスが必要。

ご清聴ありがとうございました!

これで実装してます→ GitHub: FusionTasks◦ https://github.com/kekyo/FSharp.Control.FusionTasks

◦ https://www.nuget.org/packages/FSharp.Control.FusionTasks.FS40/

スライドはブログに上げます◦ http://www.kekyo.net/

※ Thx: JavaScript プログラミング解説http://so-zou.jp/web-app/tech/programming/javascript/event/handler/