2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nemerle入門Ⅲ ~list,パターンマッチ~

Last updated at Posted at 2016-02-23

本題の前に…パイプライン演算子

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

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

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

MethodC(n : int) : int {
  System.Math.Pow(n, 2)
}

MethodAから順番に次のように実行します.

pipeline2
main() : void {
  mutable n = 0;
  n = MethodA(n);
  n = MethodB(n);
  n = MethodC(n);
}

これを,一行にまとめることもできます.

pipeline3
main() : void {
  mutable n = 0;
  n = MethodC( MethodB( MethodA( n ) ) );
}

しかし,これは非常に見づらいです.そんな時にパイプライン演算子を使います.

pipeline4
main() : void {
  mutable n = 0;
  n = (n |> MethodA |> MethodB |> MethodC);
}

読みやすくなったかと思います.パイプライン演算子を使うと可読性が上がります.

List

まず,Nemerleには,Nemerle.Core.listがあります.

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の方で説明していきます.

リストをつくる

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式でも生成ができます.

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

先頭追加 ::

演算子::は,リストの先頭に値を追加します.

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

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文

foreach
def l = [1,2,3];
foreach(n in l) {
  WriteLine(n);
}

一般的なforeach文です.

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の中のコードが実行されます.

パターンマッチ

書式は次の通りです.

patternmatch
match (some_value) {
  | pattern1 => code1
  | pattern2 => code2
  ...
}

some_valueにパターンマッチングする変数を,patternにパターンマッチングを,codeに,処理を書きます.
patternを_にすると,他のパターンでマッチしなかった場合に実行されます.(いわゆるdefault文)
C#と比較したコードを以下に示します.

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;
}
match
def n = 1;
match(n) {
  | 1 => WriteLine("One");
  | 2 => WriteLine("Two");
  | _ => WriteLine("n isn't 1 or 2");
}

わかりやすいと思います.
次に,Listのパターンマッチングについて.

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

xxs_patternmatch
match(some_list) {
  | x :: xs =>
      WriteLine($"Head is $x ");
      WriteLine($"Tail is $xs ");
  | [] => do_something();
}

このように,変数A :: 変数Bのパターンの時は,どんなリストにもマッチし,変数Aには,リストの先頭が,変数Bには,リストの先頭を除いた全体が代入され,使えるようになります.

入門Ⅳ

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?