イエス、Nimlang

2019年9月にそっとメジャーバージョンが出ていたNimlangでちょいちょい遊んでいく。
Rust勢力に押し流されそうだったところに来たから本気で嬉しい。。
今golangで作ってるgRPC基板をnimで書き換えてやろうかとか思ったけど、NimでのgRPClibは「C++の資源そのまま使うのムズイっぽいからかなり大変やで」ってなんか書いてあってその、一旦無かったことに。

こういうのって追加したい項目が増えてきた時、記事分けるのと編集追記するのとどっちがええんやろう

## 使用したもの
nim ver 1.0


## ところで何この記事
シンタックスやらなにやら確認中に「ほー」と思った部分を適当に並べます。
つまり、深いところまでやらないやつです
関係ないですがqiitaでインラインコード書こうとしてslackのと混ざって半角スペースあけてしまう病、ありませんか
シンタックスハイライトにnimがもうあるのは感動しました

## とりあえず
lowerCamelが推奨されるようです。
あと、インデントはスペースのみで、`\t`だとコンパイルが通らない模様。
当該記事とは関係ないですがWindowsプログラミングをメインでやってる方はタブ文字派多くて、unix/linuxだとスペース派が多い印象なんですけどどうなんでしょうね。
ちなみに自分は大昔に何だったかのソフトウェアがタブ文字のせいで機嫌を損ねた経験以来特に強い理由が無い限りはスペース派です。

## コンパイル&実行
https://nim-lang.org/docs/nimc.html

読めばまあ書いてあるんですが、とりあえず今現在は

```bash
nim c -r --verbosity:2 [[path/to/nimsrc]]
```
で。
verbosity2にするとコンパイル時の統計データと他にコンパイルした外部モジュール吐いてくれるので、ローカル開発段階ではとりあえず2でいいかなと。
省略すると1になるようです。1は統計とあとLint的な警告(Hint)を吐かないのかな。
挙動だけとりあえず見たいとかなら0で良いでしょう。あんまり余計なものを吐きません。

他、`-d:release`つけるとリリースビルド(恐らく中間出力されるCソースが最適化されてる)になったり、
標準モジュールのSSL関連メソッド使いたかったら`-d:ssl`つけなさいってあったりとオプション多め。
SSLのほうは全く検証してないので今度やります。

## 関数(一部)
https://nim-lang.org/docs/manual.html#types-procedural-type

### ぷらぐま
https://qiita.com/gmShiba/items/8ee07c26bdd2e71e8ced

素晴らしすぎる記事を発見したのでプラグマ関係は上記記事見れば良いかと思います。

また、この記事内ではABI気にするほどのことはしません
一応ごく簡単な一例で`{.discardable.}`を

```nim
proc test: bool = true
test() # => error
```
これはコンパイル通りません。戻り値がある関数の戻り値を`discard`無しで虚空に消すことは出来ません。
そこで

```nim
proc test: bool {.discardable.} = true
test()
```
こうすると通ります。これは「戻り値があるけど`discard`なしでの呼び出しを許可する」って感じです。
ただこれが乱発される環境って想像できないけど。


関連していわゆる`return void`な関数を呼ぶ時も、

```nim
proc test = echo "yes"
var foo = test() # => error
```
これもコンパイル通りません。`void`は受け取れません。`nil`が返りそうな気がした人はその気分を忘れましょう。

ちなみに関数定義時、引数がない場合はカッコ省略できるようです。ただ、呼び出し側はカラのカッコ要ります。

### 戻り値
#### 暗黙に宣言されているresultちゃん
いろんな記事で言及されてますが、Nimさんのprocには`result`って名前の変数が`暗黙に宣言`されています。
そして返却するものを明示しなかった場合、暗黙でその`result`が返却されます。

```nim
proc test1(): string =
  "aaa"

proc test2(): string =
  result = "aaa"
  return

proc test3(): string =
  var result = "bbb"

echo test1() # => aaa
echo test2() # => aaa
echo test3() # =>
```
rubyのように「最後に評価したもの」というよりは、「返すものが指定されていない場合、resultの中身が返る。returnが無い場合、最後に評価したものをresultに暗黙に代入する」って感じ…なのですが、test3のように同名で宣言しなおした場合、勝手に返却される能力は失われます。
個人的にはresultを返す場合であってもreturnを省略せずに書くほうが「何を返す場合でもreturnと変数名を省略するな」って一言で終わるので良いんじゃねえかなあって感があります。

#### 複数の戻り値
rubyだと配列で返却されますよね。golangだとあれ内部的にどうなってるのかまではわかりませんが異なる型であっても複数の戻り値をいっぺんに返せます。
nimの場合だと、フィールド名を省略したタプルを使って実現する感じです。これがグッドノウハウなのかはちょっとわかりませんが…

```nim
proc test(): (string,int) =
  var a = "aaa"
  var b = 777
  return (a, b)

var foo = test()
echo foo # => ("aaa", 777)
echo foo[0] # => "aaa"
echo foo[1] # => 777
```

## 変数
var/let/constを利用します。js？と思ってしまいますがjsのそれとは結構違います。っていうかjsが特殊ですね。

### const
いわゆるコンパイル時に値が確定している必要がある定数です。javascriptのconstは単に再代入不可であるというだけで、コンパイル時に確定している必要はありません。

```nim
const foo = "oh, yes!"
```
これは通ります。が、

```nim
import os

const yyy = os.commandLineParams()[0]
```
これは通りません。`cannot evaluate at compile time`って言われます。

#### 定数に関数
rubyやgoだと通らない(関数を解釈する前に定数を解釈しているからと思う)んですが、

```nim
import os
import strutils

proc test1(): int =
  result = 1 + 1

proc test2(): int =
  var a = parseInt(os.commandLineParams()[0])
  result = 1 + 1 + a

const foo = test1() # => 通る
# const foo = test2() => cannot evaluate at compile time
```
ただ個人的には可能だったところで出来ればやめてくれと言いたいところではあります

### var
再代入可能な変数。jsで言うところのletですね。宣言時に型が自明な場合は型名を省略できます。
ちなみに、const/letでも可能ですが

```nim
var
  a, b: int
  c, d = (2, 3)
```
こんなんも出来ます。

### let
constと同じですがコンパイル時に値が確定しなくても良い変数です。

```nim
import os

let yyy = os.commandLineParams()[0]
````
通ります。


## 次は
文字列関係で色々書きたいけどにちようびがおわってしまうのでまた今度