F#スクリプトでNuGetパッケージを使って爆速開発

# はじめに

今まで **C#** では **dotnet-script** を利用すれば, **NuGetパッケージ** を使ったスクリプト開発ができました.
例えば 以下のようにすることで簡単に **Json** を扱う **NuGetパッケージ** を利用することができます.

```cs:Sample.csx
#r "nuget: Utf8Json"
using Utf8Json;

var str = "{ \"key\":100 }";
var json = JsonSerializer.Deserialize<dynamic>(str);
Console.WriteLine($"key= {json["key"]}");
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125601/e7002fc3-37f0-7611-bd48-6106bd466140.png)

今回 **F# 5** で以下の構文が公式サポートされたというお話です.

```cs
#r "nuget: Utf8Json"
```

**C#スクリプト** があるんだし それでいいじゃん...
と思われるかもしれませんが **C#スクリプト** の場合はいろいろ準備しないといけないのでかなり不便です.

詳しくは **[この記事](https://qiita.com/Midoliy/items/a033b763399c242dc5c5)** を参照してください.


# 事前準備

## .NET

この機能が入ったのが **[F# 5 preview 1](https://devblogs.microsoft.com/dotnet/announcing-f-5-preview-1/)** からなので, 必然的に **.NET 5 以降** が必要になります.

そのため **[公式ページ](https://dotnet.microsoft.com/download/dotnet/5.0)** から最新の **.NET** をインストールするようにしてください.

※2020/05/07現在, **5.0.100-preview.3.20216.6** が最新


## VSCode

テキストエディタは何でもよいのですが, 最近だと **VSCode** がよく利用されると思いますので以下に必要な設定を書いておきます.

今回は F# 開発を VSCode でやる場合に最低限必要な拡張機能を紹介しておきます.

シンタックスハイライトやコード補完, インテリセンスなどが不要な方はインストールしなくても問題ありません.

### C# 拡張

**Ionide-fsharp** が依存しているので導入必須です.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125601/7736c547-65a9-3755-a63a-7ef161457aef.png)


### Ionide-fsharp 拡張

シンタックスハイライトやコード補完などの各種機能を提供してくれている拡張機能です.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125601/b78f595a-55af-8eed-4b88-2fcce1e30489.png)


### settings.json

インストールが完了したら **VSCode** の設定ファイルを編集して, **Ionide-fsharp** が **.NET Core/5** と **F# 5 preview** を使うように設定します.

```json:settings.json
{
    "FSharp.fsacRuntime": "netcore",
    "FSharp.fsiExtraParameters": [
        "--langversion:preview"
    ]
}
```

なお, **F# 5** が正式リリースされたあとについては, **--langversion:preview** が不要になります.


# 利用方法

## VSCodeの場合

まず, 適当な場所に **.fsx** ファイルを作成します.

```powershell:powershell
mkdir "D:/src/sandbox"
new-item "D:/src/sandbox/main.fsx"
```

今回, 私は `D:/src/sandbox/` に `main.fsx` というファイル名で作成しましたが, 好きな場所に好きな名称で作成していただいてかまいません.

次に **VSCode** で **main.fsx** を開きます.

```powershell:powershell
code -n "D:/src/sandbox/main.fsx"
```

そうしたら以下のように記述して, **一度 VSCode を閉じてから再度 "D:/src/sandbox/main.fsx" を開きなおします.**

```fsharp:main.fsx
#r "nuget: Utf8Json"
```

再度開きなおすことで **NuGetパッケージ** のインテリセンスが有効になります.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125601/346c4e60-a29f-d7e9-78d3-04f1910ca8bb.png)

コードを以下のように修正します.
※ **F#** には **dynamic** がないので, ちゃんと型を作成してあげます.

```fsharp:main.fsx
#r "nuget: Utf8Json"

open Utf8Json

type Foo = { Key:int }

"{ \"Key\":100 }"
|> JsonSerializer.Deserialize<Foo>
|> fun x -> printfn "Key= %d" x.Key
```

あとは実行ボタンを押せば, 実行されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125601/2b1da3c6-c783-a714-1e8c-338a73323049.png)



## dotnetコマンドを直接利用する場合

まず, コードを以下のようにします.

```fsharp:main.fsx
#r "nuget: Utf8Json"

open Utf8Json

type Foo = { Key:int }

"{ \"Key\":100 }"
|> JsonSerializer.Deserialize<Foo>
|> fun x -> printfn "Key= %d" x.Key
```

**dotnet fsi** に **--langversion:preview** を指定して, 実行します.

```powershell:powershell
dotnet fsi --langversion:preview main.fsx
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125601/9f8b6fe9-3c54-0e44-c7c6-ef9063b01caa.png)



# おわりに

控えめに言って **最高** ですね！！