dotnet new用のテンプレートを使う、作る

この記事はF# Advent Calendar 2017の6日目の記事です。 F#固有の話ではないですが、知っていると少し捗るかもしれない話をします。

dotnet newコマンドでnugetに公開されたテンプレートを使う

dotnet newは.NET Core SDKでテンプレートを用いてプロジェクトを作成するコマンドです。

https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-new?tabs=netcore2x

リポジトリはこちら:

https://github.com/dotnet/templating

標準でいくつかのテンプレートが搭載されていますが、dotnet new installコマンドを使えばnugetに公開されているテンプレートをインストールできます。

テンプレートを探すには下記サイトが便利です(公式のwikiで紹介されていたサイト)。

dotnet templates

たとえば、私を含む数名(?)で開発しているPersimmonのテンプレートはこんな感じでヒットします。

http://dotnetnew.azurewebsites.net/template/Persimmon.Templates/Persimmon.FSharp

テンプレートを作る

テンプレートの構成や設定は公式のwikiをみるのが一番です。

https://github.com/dotnet/templating/wiki/%22Runnable-Project%22-Templates

プロジェクトファイルは言語にあわせて用意します。 F#の場合は.fsprojですね(と申し訳程度のF#要素を挟んでおく)。

設定のうちshortNameは実際にdotnet newコマンドで使うので名前を吟味したほうが良いでしょう。 あとは、groupIdentityが同一でtagslanguageが異なるテンプレートが登録されていると-langオプションで言語選択できるようになります。

あと、複数言語のテンプレートを用意したいプロジェクト向けとして、1つのnugetパッケージには複数のテンプレートをほうり込めます。 これに関しては具体例をみたほうが早いので、nunitリポジトリをとりあげておきます。

https://github.com/nunit/dotnet-new-nunit

テンプレートをnugetで公開する

いつものごとくnuspecを書くわけですが、テンプレート用のパッケージであることを明示するためにmetadataタグ下にpackageTypesを追加します。

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
  ...
  <packageTypes>
    <packageType name="Template" />
  </packageTypes>
  </metadata>
  <files>
    <file src="..\templates\**" target="" />
  </files>
</package>

ファイルはテンプレートを置いているディレクトリ下のコードを全部取り込んでも問題ないことがほとんどだと思います。

おわりに

CLIで完結するのでテンプレートを作るハードルがそこそこ低いです。 publicなものに限らず社内NuGetに放り込んで運用することも可能…なはずなので、覚えておいて損はないと思います。

F# で Entity Framework Coreる

この記事はF# Advent Calendar 2017の5日目の記事です。 遅刻しましたごめんなさい…。

F# + .NET Core + Entity Frameworkの組み合わせて開発してみたときの備忘です。 もしかしたら多少古い知識が混ざっているかもれません(全部再検証するには時間がたりなかった)。

モデル定義

CLIMutableにしてEntityFramework側で処理できるようにしておきます。  また、マイグレーション機能を使うためにいくつかAttributeをつけて起きます。

open System
open System.ComponentModel.DataAnnotations
open System.ComponentModel.DataAnnotations.Schema

type UserId = int64

[<CLIMutable>]
type User = {
  [<Key; DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
  Id: UserId
  [<Required; StringLength(32)>]
  Name: string
}

DBContext

だいたいC#のサンプルを翻訳していくだけです。

open Microsoft.EntityFrameworkCore
open Microsoft.Extensions.PlatformAbstractions

type HogeDbContext() =
  inherit DbContext()

  [<DefaultValue>]
  val mutable user : DbSet<User>

  static member val ConnectionString = "" with get, set

  member this.Users
    with get() = this.user
    and set v = this.user <- v

  override __.OnConfiguring(optionsBuilder: DbContextOptionsBuilder) =
    optionsBuilder.UseMySql(SpellbookLibraryDbContext.ConnectionString)
|> ignore

ここではMySQLでの例をだしましたが、他のDBでも大した違いはないはずです。

マイグレーションコード

C#であれば Microsoft.EntityFrameworkCore.Tools.DotNet をインストールしてコマンドを叩いてあげれば C#マイグレーションコードが生成されます。

ではF#であればF#のコードをだして…くれません。

https://github.com/aspnet/EntityFrameworkCore/pull/10289

このpull requestと関連issueを読めばわかりますが、C#以外の言語はコミュニティに任せたそうな雰囲気を感じます。 とはいえ、このpull requestを含む2.1.0はまだリリースされていませんし、コミュニティでツールが作成されるのもそれなりに時間がかかるでしょう。

では、マイグレーションを諦めるのか…といえば、いやいや、方法はあります。

  1. マイグレーション部分だけC#でやる
  2. 生成されたC#コードをすべてF#に書き直す

後者に関しては、F#で書いたモデルクラスからもマイグレーションコードを生成できるので、マイグレーションコードさえなんとかしてしまえば良いわけです。

ただし、2テーブルの作成に200行ほどのF#を書かないといけないので労力に見合っていないのがネックです。

気合で書くか、待つか、ツールを実装するか。 お好みのものをお選び下さい。

F# erがOCamlを触ってみた感想

これは ML Advent Calendar 2017 2日目の記事です。

ここ半年ほど、とある社内勉強会でOCamlを使っているのでその感想をしたためておきます。 さほど中身のない内容ですがご容赦ください…。

  • ビルドツール等は5年くらい前に比べると格段に良くなった気がする
    • opam強い
    • が、jbuilderが便利かどうかはわからない…
  • コンパイル早い
    • F#比
  • エディタどうするべきかは未だ模索中
    • やはりemacsにすべきなのか…?
  • コンパイルエラーのメッセージがわかりにくい気がする?
    • 慣れの問題?
  • functor便利
    • なんでF#にないんや…
  • 第一級モジュール便利
    • F#にもほしい
  • overloadがなくてもなんとかなることを教えてくれる
    • 楽かどうかは別問題
  • F#のノリで書くとだいたいミスする
    • よくinを書き忘れる
    • 括弧(あるいはbegin end)が必要な部分に気付かないことが多い
  • いわゆる函数型言語を触った人ならなんとなくで書けそうな雰囲気
    • 知識の流用がしやすい(当然といえば当然)
    • 私が凝ったことをしていないだけ説はある

あと、プライベートな時間にppxを触ってみましたが使いどころが難しい…。 コンピュテーション式もどきを作ろうとしたのですが、なかなか良い感じにできずお蔵入りしてしまいました。

誰かppxハンズオンしてくだされ~。

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

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を直接叩くこの方法とは長い付き合いになりそう。