x10のRail操作

# はじめに

- x10のコレクションにはRail, ArrayList, Arrayなどイロイロあるらしいが、その中でもっとも基本的なコレクションであるRailの扱い方についてのメモです。
- Railはx10のもっとも基本的なコレクションで、１次元の固定長の配列を表します。C++とかJavaでいうところの配列です。
    - これをベースにしてより複雑なコレクション(ArrayListや多次元配列)も作られています。

### 参考情報
- [x10doc](http://x10.sourceforge.net/x10doc/latest/) のRailおよびRailUtils
- [lang/Rail](https://svn.code.sourceforge.net/p/x10/code/tags/SF_RELEASE_2_5_1/x10.runtime/src-x10/x10/lang/Rail.x10)
- [util/RailUtils](https://svn.code.sourceforge.net/p/x10/code/tags/SF_RELEASE_2_5_1/x10.runtime/src-x10/x10/util/RailUtils.x10)

# Rail

### 初期化

- 要素数を指定してRailの初期化。valに代入してもaの要素は変更可能。

    ```x10
val a = new Rail[Long](10);  // => [0,0,0,0,0,0,0,0,0,0]
```

    - Railの中身の出力は `Console.OUT.println` を使うと見やすく整形して出力される。
- constructorの引数にlambdaを渡して初期化

    ```x10
val b = new Rail[Long](10, (i:Long) => 3*i);
Console.OUT.println(b);     // => [0,3,6,9,12,15,18,21,24,27]
```

- 初期値を値で指定

    ```x10
val ones = new Rail[Double](10, 1.0);
Console.OUT.println(ones);    // => [1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]
```

- 任意の値を指定

    ```x10
val literals = new Rail[Long]([1,4,2,7]);
Console.OUT.println(literals); // => [1,4,2,7]
```

### for

- ループを回す

    ```x10
    for( i in a.range() ) {
      a(i) = 2 * i;
    }
    ```

### copy

- c++で言う所のコピーコンストラクタで、複製を作る

    ```x10
val a = new Rail[Long]([1,3,5]);
val b = new Rail[Long](a);
b(1) = 4;
Console.OUT.println(a);  // => [1,3,5]
Console.OUT.println(b);  // => [1,4,5]
Rail.copy(a,b);
Console.OUT.println(b);  // => [1,3,5]
```

### concat

- 二つのRailの長さを足したRailを作って、そこに内容をコピーする

    ```x10
val a = new Rail[Long]([1,2,3]);
val b = new Rail[Long]([4,5,6,7]);
val c = new Rail[Long](a.size+b.size);
Rail.copy(a, 0, c, 0, a.size);
Rail.copy(b, 0, c, a.size, b.size);
Console.OUT.println(c);  // => [1,2,3,4,5,6,7]
```

### map

- `import x10.util.RailUtils` が必要。破壊的操作、Rubyでいうところの`map!`
- 非破壊的操作にする場合は事前にcopyする必要がある

    ```x10
var a:Rail[long] = new Rail[long](10, (i:long) => i + 1);
Console.OUT.println(a);           // => [1,2,3,4,5,6,7,8,9,10]
RailUtils.map(a, a, (i:long) => i * i);
Console.OUT.println(a);           // => [1,4,9,16,25,36,49,64,81,100]
```

### find

- 要素の検索。配列がソートされていない場合。ソートされている場合は後述するbinarySearchを使うと$O(logN)$

    ```x10
    val a:Rail[Long] = new Rail[Long]([1,2,3,4,5]);
    val f = (n:Long) => { return (n%2==0); };
    var found:Long = 0;
    for( i in a.range() ) {
      if( f(a(i)) ) {
        found = a(i);
        break;
      }
    }
    Console.OUT.println(found);  // => 2
    ```

### binary_search

- `import x10.util.RailUtils` が必要
- 検索して見つかった要素のindexが返ってくる。
- 要素が見つからない場合は負の値が返る。

    ```x10
    val a:Rail[Long] = new Rail[Long]([1,2,3,4,5]);
    val index = RailUtils.binarySearch(a,5,0,a.size-1);
    Console.OUT.println(index);       // => 4
    val not_found = RailUtils.binarySearch(a,6,0,a.size-1);
    Console.OUT.println(not_found);   // => -6
    ```

### sort

- `import x10.util.RailUtils` が必要。
- デフォルトで昇順でソート。
- 第二引数に比較するための関数を渡すことができる。比較関数の返り値はIntになるようにする。

    ```x10
    val a:Rail[Long] = new Rail[Long]([2,5,1,4,3]);
    RailUtils.sort(a);
    Console.OUT.println(a);      // => [1,2,3,4,5]
    RailUtils.sort(a, (n1:Long,n2:Long)=>{
      return (n2-n1) as Int;
    });
    Console.OUT.println(a);      // => [5,4,3,2,1]
    ```

### sort_by

- 比較に使う関数を指定する場合は以下のように書く
- `import x10.util.RailUtils` が必要。

    ```x10
    val a:Rail[Long] = new Rail[Long]([2,5,1,4,3]);
    val f = (n:Long) => {
      return n%4;
    };
    RailUtils.sort(a, (n1:Long,n2:Long)=> {
      return (f(n1) - f(n2)) as Int;
    });
    Console.OUT.println(a);      // => [4,1,5,2,3]
    ```

### reduce

- reduction演算
- `import x10.util.RailUtils` が必要。

    ```x10
    val a:Rail[Long] = new Rail[Long]([1,2,3,4]);
    val sum = RailUtils.reduce(a, (acc:Long,x:Long)=>{acc+x}, 0);
    Console.OUT.println(sum);     // => 10
    val prod = RailUtils.reduce(a, (acc:Long,x:Long)=>{acc*x}, 1);
    Console.OUT.println(prod);     // => 24
    ```