"F# でのテスト用 DSL について考える"で書いたコンピュテーション式
発端や流れに関しては
F# でのテスト用 DSL について考える — a wandering wolf
を読んでください。
本記事では私が実装してみたコンピュテーション式についてゆるく説明します。
先に読むべきもの
コンピュテーション式の実装にStateを用いる - pocketberserkerの爆走
第1版
do!
で失敗したら移行を実行しない- それ以外はとりあえず実行する
みたいな話があったので、ぱっと思いついた Source メソッドを悪用する方針で攻めることにしました。 Source メソッドをオーバーロードすることで、unit型かそれ以外の型かをBindメソッドなどに伝えます。
このタイミングはここで時間切れだったので、中途半端な状態で公開しました。
第2版
テスト結果は、失敗したときにその理由を1つだけ持つのではなく、複数の失敗を持てる、的な
@bleis 最近、それがJUnitで流行っている。soft assertって名前で。
2014-10-22 14:42:55 via TweetDeck to @bleis
こういう話と、bleis さんの実装した
を眺めながらいじったコードが以下になります。
https://gist.github.com/Gab-km/86dd730a8d8e407a699f に触発された何か
Bindメソッドの基本はbleisさんのものを借りつつ、Value に入力型を持たせることで失敗したアサーション以降のアサーションも実行できるようにしました。
Unchecked.defaultof
を使っているので危険では?という意見もあるかもしれませんが、 `let! _`` で捨てる前提なので、これでいいかな、と。
第3版
とはいえ、 let! _
はあまりきれいじゃない気がしますし、どうせなら yield!
のほうがよさそうだよね、ということでさらにいじりました。
https://gist.github.com/Gab-km/86dd730a8d8e407a699f に触発された何か
過去に紹介した、引数で状態を引き回す方法を使ってCombineを実装することにより、 yield!
を連続で呼び出すことが可能です。
Sourceメソッドで注意すべき点
Sourceメソッドはそこそこ変換に現れるので、型合わせるのが簡単ではないです(そこまで難しいわけでもないですが)。
最終版の場合だと、Source メソッドで結果、型情報、状態を生成して型をあわせつつ、YieldFromやReturnFromで状態のみ書き換えるとかしてしのいでいます。
おわりに
実用化?知らない子ですね。