Nemerle入門Ⅲ ～list，パターンマッチ～

## 本題の前に…パイプライン演算子
F\#のパイプライン演算子と似たものがNemerleにもあります．  
3つの関数があるとします．

```nemerle:pipeline
MethodA(n : int) : int {
  n + 2
}

MethodB(n : int) : int {
  n * 2
}

MethodC(n : int) : int {
  System.Math.Pow(n, 2)
}
```
MethodAから順番に次のように実行します．

```nemerle:pipeline2
main() : void {
  mutable n = 0;
  n = MethodA(n);
  n = MethodB(n);
  n = MethodC(n);
}
```
これを，一行にまとめることもできます．

```nemerle:pipeline3
main() : void {
  mutable n = 0;
  n = MethodC( MethodB( MethodA( n ) ) );
}
```
しかし，これは非常に見づらいです．そんな時にパイプライン演算子を使います．

```nemerle:pipeline4
main() : void {
  mutable n = 0;
  n = (n |> MethodA |> MethodB |> MethodC);
}
```
読みやすくなったかと思います．パイプライン演算子を使うと可読性が上がります．

# List
まず，Nemerleには，`Nemerle.Core.list`があります．

```nemerle:Nemerle.Core.list
def l : list[int] = [0, 2];
def ll : List[int] = List();
l.GetType().ToString() |> WriteLine;
ll.GetType().ToString() |> WriteLine;
```
上の例では，1行目にNemerleの構文で作ったリスト，2行目に.Net標準のクラス`System.Collections.Generic.List`を作ってます．
これを実行すると,
>Nemerle.Core.list\`1+Cons[System.Int32]
System.Collections.Generic.List\`1[System.Int32]

このように違います．本記事では，`Nemerle.Core.list`の方で説明していきます．

## リストをつくる
```nemerle:make_lists
1  def emptyList = []; // result: []
2  def allwritedList = [0, 1, 2, 3]; // result: [0, 1, 2, 3]
3  def rangeList = $[0 .. 3]; //result; [0, 1, 2, 3]
4  def rangeListWithStep = $[1, 3 .. 10]; //result: [1, 3, 5, 7, 9]
5  def rangeListWithFunction  = $[i * i, i in [1 .. 5]]; //result: [1, 4, 9, 16, 25]
6  def rangeListWithCondition = $[i, i in [1 .. 5], i % 2 == 0]; //result: [2, 4]
```
リストの生成には，C\#のリスト生成記法に似た方法で記述ができます．  
また，PythonやF\#にもあるようなZF式でも生成ができます．

## リスト関連の様々なメソッド

### 先頭追加 `::`
演算子`::`は，リストの先頭に値を追加します．

```nemerle:AddList
def A = 2 :: [];
  // A is [2]
def B = 3 :: A;
  // B is [3, 2];
```

### Head,Tail,Last
`Head`はリストの先頭，`Tail`はリストから先頭を除いた全体（要するにリストの2個目以降）を返します．
Lispでいう，`car`,`cdr`みたいなものですね．
`Last`は名前のとおりです．

### Filter,Map
```nemerle:filter,map
def a = $[1 .. 5];
WriteLine(a.Filter(fun(i) { i % 2 }));
//result: [2, 4]
WriteLine(a.Map(fun(i) { i * 2 }));
//result: [2, 4, 6, 8, 10]
```
`Filter`はLINQの`Where`みたいなもので引数の関数が`true`を返す値だけのリストを返します．
`Map`はLINQの`Select`みたいなもので引数の関数をリストの各要素に適用します．

### 遅延評価リスト
LINQは遅延評価ですが，Nemerleの`List`は正格評価も遅延評価もでき，`lazy`がついたメソッドを使えば遅延評価でできます．

### foreach文

```nemerle:foreach
def l = [1,2,3];
foreach(n in l) {
  WriteLine(n);
}
```
一般的なforeach文です．

```nemerle:foreach
def l = [1,2,3];
foreach(n is int in l) {
  WriteLine(n);
} otherwise {
  WriteLine("There are no elements.");
}
```
2行目，`is`で型指定ができ，その型の値のみをリストから取り出すことができます．
`is`ではなく，`:>`にすると，リストにその型に合わない値が含まれていた場合，例外を投げます．
4行目～，もし，一回もforeach内のコードが実行されなかった場合，otherwiseの中のコードが実行されます．

# パターンマッチ
書式は次の通りです．

```nemerle:patternmatch
match (some_value) {
  | pattern1 => code1
  | pattern2 => code2
  ...
}
```
some_valueにパターンマッチングする変数を，patternにパターンマッチングを，codeに，処理を書きます．
patternを`_`にすると，他のパターンでマッチしなかった場合に実行されます．(いわゆる`default`文)
C#と比較したコードを以下に示します．

```csharp:switch
int n = 1;
switch(n) {
  case 1:
    Console.WriteLine("One");
    break;
  case 2:
    Console.WriteLine("Two");
    break;
  default:
    Console.WriteLine("n isn't 1 or 2.");
    break;
}
```
```nemerle:match
def n = 1;
match(n) {
  | 1 => WriteLine("One");
  | 2 => WriteLine("Two");
  | _ => WriteLine("n isn't 1 or 2");
}
```
わかりやすいと思います．
次に，Listのパターンマッチングについて．

```nemerle:ListPatternMatch
match (some_list) {
  | [42, 42] => "two forty-two"
  | [42, _] => "forty-two on first position of two-element list"
  | [_, 42] => "forty-two on second position of two-element list"
  | 42 :: _ => "forty-two on first position"
  | _ :: 42 :: _ => "forty-two on second position"
  | [] => "an empty list!"
  | _ => "another list"
}
```
上から5つは，リストの部分マッチです．`_`は，任意の値という意味です．
`[ ]`で，パターンマッチすると，要素数が限定されてしまいます．上の例では，パターンの`[]`内に，2つの要素があるので，長さが2のリストだけにマッチします．
` :: `で，パターンマッチすると，要素数は限定されませんが，`::`の右側の要素にはリストの値しかいれることができません．従って，`22 :: _ :: 12`というようなことはできません．

上から6つ目の`[]`は空のリストとマッチします．

## head::tail
```nemerle:xxs_patternmatch
match(some_list) {
  | x :: xs =>
      WriteLine($"Head is $x ");
      WriteLine($"Tail is $xs ");
  | [] => do_something();
}
```
このように，`変数A :: 変数B`のパターンの時は，どんなリストにもマッチし，`変数A`には，リストの先頭が，`変数B`には，リストの先頭を除いた全体が代入され，使えるようになります．

# 〆
[入門Ⅳ](http://qiita.com/Gnico/items/72d8f17fef52100963a6)へ