Nemerle入門Ⅰ ～インストール，言語説明，C#に近い機能の説明～

筆者の動作環境は，Nemerle入門の目次をご覧ください．

# ダウンロードとインストール
[このページ](http://nemerle.org/Downloads)からダウンロードできます．
残念ながら，最近のVisual Studioには拡張機能が対応していません．

# Nemerleとは
C#，Lisp，Ruby，Python等，沢山の言語機能を詰め合わせた.NET Frameworkで動く言語です．

## Macro(メタプログラミング)
Nemerleの注目機能の一つ，Macroによって，柔軟な[メタプログラミング](https://ja.wikipedia.org/wiki/メタプログラミング)ができます．
今後紹介する，if文，foreach文などの文はほとんどMacroによって実装されています．色々工夫すれば，Nemerleを様々な言語の書き方で書けるようになります．この機能によって，アスペクト指向プログラミング，部分評価，ドメイン固有言語の組み込みとかできるらしいです．(Wikipediaより)

## 関数型プログラミングがC#よりもやりやすく，F#よりC#風に書ける
Nemerleはそれぞれの言語の良さを取り入れている（主観）ので，イケてます．

## イケてる型推論
```n:型推論
def li = List(); //コンストラクタで初期化
//liはジェネリック型List[T]と宣言される
def n = 1;
//int型のnを宣言，1を代入
li.Add(n);
//liはList[int]と型推論される．
li.Add("Nemerle");
//ﾃﾞｷﾅｲﾖ
```
もちろん，C#はできません．

```csharp:型推論
var li = new List<>(); //Compile Error!
//ﾃﾞｷﾅｲﾖ
var n = 1;
//int型のnを宣言，1を代入
li.Add(n);
//だからliってﾅﾝｿﾞﾔ
li.Add("Nemerle");
//だから，ﾃﾞｷﾅｲﾖ
```

# プロジェクトの作成，どこにコード書く？
Visual Studioから新しい**Nemerle**の**ConosleProject**を作ってください．
こんな感じのソースコードが出てくるはずです．

```nemerle:Main.n
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Console;
using System.Linq;

module Program
{
  Main() : void
  {
    WriteLine("Hi!");
    _ = ReadLine();
  }
}
```
実行してみて，"Hi!"が表示されて，なんか入力して，Enter押すと黒画面が閉じるはずです．
これから，"WriteLine("Hi!")"の部分を書き換えていきます．

# 変数・定数，初期化，代入(束縛)
### 宣言
> mutable name : type = value
def name : type = value

または
> mutable name = value
def name = value

nameには変数名，typeには型名，valueは値を入れます．
変数はmutable,定数はdefを用います．
上は，型を指定して宣言，下は，型推論をしています．型推論の場合，宣言時に型がわかるような代入・初期化をしなくても結構です．

```nemerle:型推論
mutable x = null; //xってどうなるの？
x = Console.ReadLine(); //ReadLineの戻り値はstring．すなわち，xはstring型なのか！！
```

### 初期化(コンストラクタの呼び出し)
intなど，プリミティブ型などは，`def hoge = 1`で結構ですが，その他は，コンストラクタを呼ぶ必要があります．ここでは，**一般的な型**のコンストラクタの呼び出しを説明します．

```nemerle:コンストラクタ
def name = type_name(arguments) //非ジェネリック型
//例
    def string_builder = StringBuilder();

def name = type_name.[T](arguments) //ジェネリック型
//例
    def lazy_object = Lazy.[string]();
```
### クラス変数を指定しながら初期化
文法がC\#と少し違います．

```nemerle:コンストラクタとクラス変数の指定
class some {
  public n : int;
  public m : int;
  public this() {
    WriteLine("Constractor is called.");
  }
}

def s : some = some() <- {
  n = 0;
  m = 0;
}
```
### 代入(束縛)
C#などと同じ "=" イコールで代入します．

# プリミティブ型
[C#と全く同じです．](https://msdn.microsoft.com/ja-jp/library/ya5y69ds.aspx)

# 条件分岐
## 条件分岐に関す売る演算子(比較演算子，条件演算子)
[C#と同じです．](https://msdn.microsoft.com/ja-jp/library/6a71f45d.aspx)

## 条件がTrueの場合，Falseの場合で分岐させる(if文)
```nemerle:if
if(condition) {
  A
} else {
  B
}
```
両方共，conditionがTrueの時は，Aのコードを，Falseの時は，Bのコードを実行します．
C#のようにカッコを省略することができます．**しかし，elseは省略できません．**

## 条件がTrueの場合のみ実行する(when文)
```nemerle:when
when(condition) {
  Code
}
```
conditionがTrueの時，Codeが実行されます．

## 条件がFalseの場合のみ実行する(unless文)
```nemerle:unless
unless(condition) {
  Code
}
```
conditionがFalseの時，Codeが実行されます．
（when文で，論理否定演算子使って済ませることが自分は多いので，影が薄い文です．）

# コメント
C\#,C++と同じです．

```nemerle:comments
//一行コメント
/*
   複数行コメント
*/
```

# スプリクト言語風書き方
プロジェクト作成時のMain.nは，(usingの部分は省いてます．)

```nemerle:Main.n
module Program {
  Main() : void {
    WriteLine("Hi!");
    _ = ReadLine();
  }
}
```

こうなっていたと思います．これらをコメントアウトしてください．(Ctrl + K,C)
そして以下のソースコードをコピペして，実行してみてください．

```nemerle:Main.n
WriteLine("Hi!");
_ = ReadLine();
```
\
実行できましたね？このように，スクリプト言語のように書くこともできます．  
（C\# 10にも同様の機能が実装されました．）  

# アクセス修飾子
publicやprivate等，[C#と同じです](https://msdn.microsoft.com/ja-jp/library/ms173121.aspx)．  
現在，

# static,volatile,partial
これらもC#と同じです.

# メソッド
```nemerle:Method
Method_Name(Parm1 : type, Param2 : type...) : Return_Type {
  Code
}
```
書式はこんな感じ．F#っぽいかな？これだけ見てもわからないので，具体例を示しましょう．

```csharp:Method
void HogeHogeMethod(int start, int count) {
  //DoSomething
} //C#
```
```fsharp:Method
let hogeHogeMethod (start : int, count : int) =
  //DoSomething
  ()
```
```nemerle:Method
HogeHogeMethod(start : int, count : int) : void {
  //DoSomething
} //Nemerle
```

上の3つはほぼ同じです．
書き方はC#をF#みたく書いた感じでしょうか．
属性の付け方はC#と同じです．

### 関数
C#ならば，

```csharp:return
int Add(int x, int y) {
  return x + y;
}
```
ですが，Nemerleでは，returnは要りません．最後の式の戻り値が返されます．

```nemerle:return
Add(x : int, y : int) : int {
  x + y;
}
```
## namespace
C#/VB.netのnamespaceと同じです．

```nemerle:namespace
namespace hoge {
  class hoge {
    ...
  }

  module hogeUtil {
    ...
  }
}
```

## class
C#/Vb.netのclassと同じです．
クラスを定義することができます．
クラスの定義の仕方は後で詳しく説明します．

```nemerle:class
class hoge {
  mutable a : int;
}

Main() : void {
  def h = hoge();
  h.a = 0;
  WriteLine(h.a);  // 0
}
```

## module
VisualBasic .Netのmoduleと同じです．C#で言う，static classのようなものです．
moduleの中に書いた物は自動的にStaticになります．
インスタンス化はできないので，通常のクラスのコンストラクタなどは作れません．

```nemerle:module
module Num {
  Add(x : int, y : int) : void {
    x + y
  }
}

Main() : void {
  Console.WriteLine(Num.Add(3, 5)); // 8
  def n : Num = Num(); // Error!!
}
```

## クラスの定義
Nemerleでも，もちろん.Netのクラスを定義することができます．他の言語と同じで，プロパティなども定義することができます．そこまで，C\#/VB .netと差異は無いので軽く流します．

```nemerle:class
class IntPair {
  mutable a : int; //メンバ変数(アクセス修飾子がないので，自動的にprivateになる)
  public mutable b : int; //アクセス修飾子がつけられる
  private c : int; //局所定数(変更はできない)
  static class_name : string = "IntPair";
    //staticをつければ静的に，”=”で代入もできる

  public A : int { //プロパティ，C#と同じなので，そこまで気にしなくていい
    get{
      WriteLine("A is called!");
      a;
    } set{
      a = value;
    }
  }

  public D : int { get; } //getオンリーなプロパティもこの一行でおｋ

  public this() { //コンストラクタ
    a = 0;
    b = 0:
    c = 0;
  }

  public static this() { //静的なコンストラクタ
    WriteLine("IntPair!");
  }
}
```
残念ながら，C\# 9の`init`には対応していません．

## 構造体: `struct`
`class`ではなく，`struct`にすることで構造体を生成できます．
```nemerle:struct
struct StructBox {
  public mutable x : double = 0;
  public mutable y : double = 0;
}
```

## レコード: `Record`
`class`もしくは`struct`に`[Record]`マクロをつけると，C\# 10のレコードのようになります．

```nemerle:record
[Record]
class Point {
  public mutable x : double = 0;
  public mutable y : double = 0;
}
```

# キャスト
Nemerleにキャストは2種類あります．

### 厳密な型変換（：）
コンパイル時にチェックされ，型変換できるかわからない時は，コンパイルエラーを吐きます．

```nemerle:type_enforcement
def s : short = 72;
WriteLine(200000000 / (s : long)); // short → longは元がどんな状態でも変換できるので，おｋ

def obj : object = 18;
WriteLine(200000000 / (obj : long)); // Compile Error!
```

### 普通の型変換（:>）
実行時にチェックされ，失敗した場合，`InvalidCastException`を投げます．

```nemerle:type_cast
def a : object = "abc";
WriteLine(20000000 / (a :> long)); // コンパイルエラーはないけど，例外投げる
```

# おわりに
[入門Ⅱへ](http://qiita.com/Gnico/items/43a84aed8e8d6468ba47)