新しい言語を触り始めた時に実装してみるもの一覧

ajitofm 13に「言語を学ぶ時に練習で何を実装してみるか」みたいな話が出ていた。 で、自分は何やっているかなーと思ったので書き出してみる。

全部やるってわけではなく、目的に応じていくつかやってみる感じ。

  • parser combinator
    • パフォーマンスを求めないなら数日で実装できる
    • 文字列操作
    • 最適化の練習(文字列編)
  • JSON serializer
    • parser combinatorを使って何かやってみる時の定番?
    • quickcheck的なライブラリを練習するのにちょうど良い
  • binary serializer
    • バイナリ操作
    • マクロ
    • 最適化の練習(バイナリ編)
    • msgpackが仕様の大きさ的にやりやすい?
  • データ構造
    • ひとつひとつは小さいので練習しやすい
    • データ構造、アルゴリズムの復習を兼ねる
  • TODOリスト
    • Webフレームワーク
    • DB
    • logging
  • テスティングフレームワークアサーション
    • リフレクション、メタプログラミング
    • AST変換(power assertもどきを題材に)
    • 同値比較の考察に便利?
    • 完成度は重視しない

他の人がどういうことをやっているのか気になるところ。

技術書典3で F# 入門的なものをだします

なんとかまにあってよかった…。


表示はこんな感じ

f:id:pocketberserker:20171019175103p:plain

高階ことりちゃんの画像は以下のサイトからお借りしました。 CC BY-SA 3.0だそうです。

高階ことり Website

内容としては.NET Core 2.0でF#に入門する的なものになります。 といっても半分くらい文法説明です。

  1. Hello F#
  2. F#の文法
    • ひたすら雑多に文法を説明
  3. 簡単なWeb APIを作ってみる
  4. さらに先へ進むために

500円の予定です。 今のところ電子版の予定はありません。

Utf8Json.FSharpExtensions 0.1.0を試験的にリリース

ある朝、目が覚めたらUtf8Jsonのリリース話とともにメンションが飛んできていました。

ほげぇ、と言いつつ簡単な部分だけ作ったので公開しておきます。

NuGet Gallery | Utf8Json.FSharpExtensions 0.1.0

0.1.0で対応しているのは以下の型です。

  • Option
  • list
  • set
  • map

recordとstruct recordは別に上記ライブラリを使わなくても動きます。

判別共用体は対応するか悩み中です。 そんなに使うのかなぁ、というのが悩んでいる理由です。 でもJSON.NETはサポートしているらしいんですよね…うむむ。

vstestで.NET Coreプロジェクトのコードカバレッジをとる

temporary workaroundらしきものがドキュメントにのっていたのでメモ。

https://github.com/Microsoft/vstest-docs/blob/3c64cbc1a387d6f7f9ebc82a953246322d94cd5c/docs/analyze.md#working-with-code-coverage

こっちのissueが解決されれば、dotnet testコマンドで実行できるようになるようだ?

https://github.com/Microsoft/vstest/issues/981

とはいえ現時点でスケジュールが確定していないので、vstest.console.exeを直接叩くこの方法とは長い付き合いになりそう。

F# で使われるユニットテスティングフレームワークなどの紹介

前にもかいたことがある気がするけれど、2017年度版ということでどうか。 "フレームワーク"と書きつつライブラリも混ぜます。

NUnit

http://nunit.org/

  • よくみかけるやつその1
  • 古の時代から存在するとされている
  • 最近になってウェブサイトがモダンに
  • 地味に進化を続けている
  • .NET Coreに対応している

最近だと

という話を見かけて「へぇ〜」っとなった。 しかしこのAssert.Multipleはどうやって動いているのだろう…?

個人的にもう使う機会はないだろうと思いつつ、なんだかんだ参考になることがあるのでソースは読むだろう。 なんとかUnitに慣れている人ならかける。

xUnit.NET

https://xunit.github.io/

  • よくみかけるやつその2
  • .NET Foundationのもちもの
  • .NET Coreに対応している

コミュニティ的なリソースがあるためか、開発速度がダントツで早い気がする。 .NET界隈(特にC#界隈)のデファクトになる(なっている?)のではないでしょうか。

個人的には、F#製ではないフレームワークの中でならAssertionが好みなのでこれを選ぶ。

MSTest

https://github.com/Microsoft/testfx

  • かつてVisual Studioに標準搭載されていたやつ
  • .NET Coreに対応している

特筆すべきことはない…私が知らないだけかもしれませんが。 新規で使う理由も、特にない…?

FsUnit

https://fsprojects.github.io/FsUnit/

  • NUnitやxUnit.NETといったどちらかといえばC#, VB.NET向けフレームワークAPIをラップしたもの
  • FsUnitTypedというモジュールを使えばAssertionの型チェックを厳密に行える

F# 界隈では一時期みんなこれを使っていたような…今はどうかわからない。 個人的には、shouldみたいなAPIを覚えていられない記憶力になったので使わないと思います。

FsCheck

https://fscheck.github.io/FsCheck/

  • Propery Based TestingとかRamdom Testingとか呼ばれる類のツール
  • 一応単独で実行できる仕組みがある
  • とはいえ、他のテスティングフレームワークと組み合わせる場合がほとんど

Persimmon以外のテスティングフレームワークなら使わない選択肢がない。

expecto

https://github.com/haf/expecto

後述するPersimmonとは違う意味で独特なAPIです。 コンピュテーション式を使い分けることでSync、Async向けテストをかき分けられる。

私にはPersimmonがあるので使わないですが、興味がある方はさわってみると良いかも。

Persimmon

http://persimmon-projects.github.io/Persimmon/

  • F#向けというかF#専用
  • APIが独自路線な関係でいろんなライブラリを再実装している
  • .NET Coreでも一応動く
  • コア開発者が日本人

ライブラリはなぜか色々ある。 名前と機能の関連がわかりにくいという噂あり。

開発者バイアスがかかるので所感は書きません。

unquote

http://www.swensensoftware.com/unquote

  • F#でpower assertしたい的なやつ

他言語のpower assertに比べるとちょっと見劣りする気がしなくもない…?

canopy

http://lefthandedgoat.github.io/canopy/

  • Web UIテスト

F#でかけるよやったね、以上も以下もない気がする。

Foq

https://github.com/fsprojects/Foq

  • テスティングフレームワークと書いてあるが、モックライブラリと認識している人が多い気がする

おわり

数年前に比べて選択肢は増えたが、まだまだ競合が少ない気がする。

Persimmon.Script 2.0.0をリリースした

NuGet Gallery | Persimmon.Script 2.0.0

Persimmon v2を作る過程で「使う人いないし消そう」となってdropしたのですが、最近になってほしいという人が現れたので、v2ようにマイグレーションするくらいなら労力かからないだろうということで復活させました。

まぁ、労力は予想以上に必要でしたが…1日で終わると思ってたら色々試行錯誤したりで3日くらいかかってしまった。

使い方は簡単で

#r @"../packages/examples/Persimmon/lib/net45/Persimmon.dll"
#r @"../packages/examples/Persimmon.Runner/lib/net40/Persimmon.Runner.dll"
#r @"../src/Persimmon.Script/bin/Release/net45/Persimmon.Script.dll"

// このあたりにテスト書く

Script.collectAndRun (fun _ -> Assembly.GetExecutingAssembly())

Script内にテストを書き連ねた後にAssembly.GetExecutingAssembly()スクリプト自身のAssemblyをターゲットとしてテストを収集、実行するだけです。

個人的にはテスト用のdll作ってしまうので使う機会がなさそう…ということもあってメンテナンスを継続するかどうかは期待しないほうが良いです。 あくまでdll作ってテストするまでもないもの(そんなものあるのか…?)に対して使用しましょう。

呪文詠唱!F# #ML_study

ML勉強会 #2 - connpass

発表してきました。

要約

F#のコンピュテーション式を使うと呪文詠唱できます。 呪文詠唱自体に実用性はありませんが、やっていることは応用が効くかもしれません。

はじめに

突然ですが問題です。 

詠唱 {
  モナドは
  単なる
  自己関手の
  圏における
  モノイド対象だよ
  何か問題でも
  ``?``
}

このコードはF#的にvalidでしょうか?

正解

コンピュテーション式用のビルダークラスを適切に準備してあげればvalidになります。

中身

MLStudy2/Program.fs at 78359cf52503daa0c40cf5fed50a60dc89e5c9df · pocketberserker/MLStudy2 · GitHub

要するものは以下のとおり

  • コンパイルできるコードを制限するための型
    • 名前はなんでも良いので、今回はLine0とかつけてます
    • 別に判別共用体でなくても良いですが、シングルトンを作りやすいものが良いでしょう
  • Attributeから値を取得するためのヘルパー関数
    • カスタムオペレーター用のメソッドに指定したAttributeを取得し、そこから情報を抜き出します
  • カスタムオペレーターが定義されたコンピュテーションビルダー
    • カスタムオペレーターを使うことで、任意の文字列をコンピュテーション式のキーワードとして扱える
    • 中身はなんでも良い
    • 今回は呪文詠唱っぽくみえるよう、1秒ごとに呪文を出力している
    • Runコンパイル制限用に使っていた型の値を取り除く

コンピュテーション式は、展開規則に従ってビルダーに存在するメソッド呼び出しに展開されます。 この時、引数や戻り値の型を適切に実装すればあるオペレーターが呼ばれない限りコンパイルエラーとか、指定の順序で呼び出さない限りコンパイルエラーとなるようにできます。

今回のコンピュテーション式は呪文なので、カスタムオペレーターの呼び出し順序は固定です。 呪文は少しでも間違えると発動しない(つまりコンパイルエラー)なのは当然ですよね?

無詠唱

発表中は「無詠唱なんて許さない」と言いましたが、つくれないことはありません。 ビルダーにZeroメソッドを用意することで、無詠唱のようなことが行えます。

詠唱 { () }

https://github.com/pocketberserker/MLStudy2/blob/78359cf52503daa0c40cf5fed50a60dc89e5c9df/src/MLStudy2/Program.fs#L67

Zeroメソッドを定義する際の注意点は以下のとおりです。

  • ビルダークラスに定義されたカスタムオペレーター用のメソッドを全て取得
  • 上記実装はザルに作ったので実行順序が処理系依存ですが、詠唱順序をちゃんと固定したいなら、メソッド名をソートしやすいものにしたほうが無難
  • キーワード名とメソッド名は別でも問題無い
    • デバッグ時にわかりやすくするために名前を合わせることが多いとは思う

コンピュテーション式用のビルダーを生成できないのか?

ファイルから読み込んだ文字列群を用いてTypeProviderでビルダーを生成すれば、任意の詠唱を生成できるのでは、という話をしました。 残念ながら当日には間に合いませんでしたが…。

で、これについて昨日検証してみたところ、現場のコンパイラだと不可能っぽいという結論に至りました。

  • 必要なビルダークラスとメソッド、型までは消去型なら用意できる
    • 生成型は複数の型を生成できる気がしない…
  • 生成したビルダーのカスタムオペレーターがコンパイラにカスタムオペレーターだと認識されない

もしかしてコンパイラのバグだったらどうしよう。

https://github.com/pocketberserker/MLStudy2/blob/288cd0b25fd4cbc28c2dc80439bbc4a6a8a5992f/src/MLStudy2/Program.fs#L90

コードは公開しているので、検証したい方は好きにいじってください。

補足?

Indexed MonadをF#で用意できるのかは不明ですが、やりたいことは同じかと。 今回は時間がなかったのでごり押しでコードを書いてしまいました。

まとめ

言語機能を使って遊ぶのはとても楽しいです。