Page Top

レンジの概要 anchor.png Edit

レンジは一般にコンテナと呼ばれる、内部に複数のデータを保有するようなオブジェクトが、特定のメンバ関数やプロパティを実装することで統一的に操作できる仕組みを提供します。 レンジには実装する関数やプロパティによりいくつかの種類があります。

InputRange (入力レンジ)
empty、front、popFront を提供する。
OutputRange (出力レンジ)
put を提供する。
ForwardRange (前進レンジ)
入力レンジに加え、save を提供する。
BidirectionalRange (双方向レンジ)
前進レンジに加え、back、popBack を提供する。
RandomAccessRange (ランダムアクセスレンジ)
双方向レンジに加え、length、opIndex を提供する。

上記のレンジは出力レンジを除き、包含関係になっており、ランダムアクセスレンジが最も多くの関数を提供する必要がある反面、より多くのレンジを対象とする関数を使用できます。しかしランダムアクセスレンジであれば全ての関数を適用できるというわけではなく、使用する関数によっては更に opIndexAssign や opSlice なども提供する必要があります。

Page Top

Rangeの主な特性 anchor.png Edit

hasMobileElements
moveFront プリミティブを持ち、双方向あるいはランダムアクセスレンジなら更に moveBack と moveAt をサポートする
hasSwappableElements
前進レンジでswap可能な要素型を持つ
hasAssignableElements
前進レンジで代入可能な要素型を持つ
hasLvalueElements
左辺値要素*1を持つ
hasLength
整数型の値を返す length メンバを持っている
isInfinite
emptyが常にfalse
hasSlicing
整数を指定するスライス演算子を持ち、入力レンジを返す
Page Top

レンジを利用する利点 anchor.png Edit

例えば、std.container.SList は要素数を返すプロパティを持っていませんが、レンジを内包していますので、std.range.walkLength を使えば要素数が得られますし、何らかの理由で独自のコンテナクラスを実装する場合でも、レンジの条件を満たせば レンジを対象とする既存の関数が使用できるメリットがあります。

Page Top

レンジを使用する例 anchor.png Edit

Page Top

配列 anchor.png Edit

配列ははじめから empty や front などを持っているので、レンジとしての条件を満たしており、ランダムアクセスレンジです。

std.range.walkLength
レンジの要素数を返す。
std.algorithm.canFind
レンジに指定した要素があれば true、そうでなければ false を返す。
std.algorithm.remove
レンジから指定したオフセットの要素を取り除き、残りのレンジを返す。
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 
 
 
 
 
-
|
|
-
!
|
|
|
|
|
!
module test;    // dmd 2.055
 
import std.algorithm, std.range, std.stdio;
 
void main()
{
  int[] array = [ 2, 4, 6, 8, 10 ];
  
  // 配列は length プロパティを持っているので、本来は walkLength を使う必要は無い。
  writeln(walkLength(array));    // 5
  
  writeln(canFind(array, 6));    // true
  writeln(canFind(array, 7));    // false
  
  writeln(remove(array, 2));    // [ 2, 4, 8, 10 ]
}
Page Top

SList anchor.png Edit

std.continer.SList 構造体は内部にレンジを持っています。SList は単方向連結リストのコンテナです。

Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 
 
 
 
 
-
|
|
-
!
|
|
|
|
-
|
!
module test;    // dmd 2.055
 
import std.algorithm, std.container, std.range, std.stdio;
 
void main()
{
  auto sList = SList!(int)(2, 4, 6, 8, 10);
  
  // SList は opSlice がオーバーロードされており、このスライス演算子がレンジを返すようになっている。
  writeln(walkLength(sList[]));    // 5
  
  writeln(canFind(sList[], 6));    // true
  writeln(canFind(sList[], 7));    // false
  
  // remove が必要とするレンジの条件を完全には満たさないので、使用できない。
  // auto range = remove(sList[], 2);
}
Page Top

レンジを実装する例 anchor.png Edit

入力レンジを持つコンテナを実装します。empty や front など、それぞれの関数が持つべき意味通りに正しく実装しなければ、うまく動作しません。

empty
レンジにまだ要素が残っている場合に false を返す。
front
レンジの現在の先頭の要素を返す。
popFront
レンジの先頭の要素を次に進める。
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
 
 
 
 
-
|
|
|
|
|
|
|
!
 
 
-
|
|
|
-
|
!
|
-
!
-
|
!
|
|
-
|
|
|
|
-
|
!
|
|
-
|
!
|
|
-
|
!
|
|
-
|
!
!
!
module test;    // dmd 2.055
 
import std.algorithm, std.stdio;
 
void main()
{
  auto container =  TestContainer!(int)([0, 2, 4, 6, 8, 10]);
  
  foreach(v; container[])
    writeln(v);    // 0, 2, 4, 6, 8, 10
  
  writeln(canFind(container[], 6));    // true
  writeln(canFind(container[], 7));    // false
}
 
struct TestContainer(T)
{
  private T[] data;
  
  this(T[] value)
  {
    data = value;
  }
  
  // レンジはスライス演算子から返す。
  Range opSlice()
  {
    return Range(this);
  }
  
  struct Range
  {
    TestContainer outer;
    int frontCursor;    // 現在着目している位置を表す。
    
    this(TestContainer o)
    {
      outer = o;
    }
    
    @property bool empty()
    {
      return frontCursor >= outer.data.length;
    }
    
    @property T front()
    {
      return outer.data[frontCursor];
    }
 
    void popFront()
    {
      ++frontCursor;
    }
  }
}

Page Top

投票とコメント anchor.png Edit

選択肢 投票
大変参考になった4  
参考になった1  
あまり参考にならなかった0  
まったく参考にならなかった0  

コメントはありません。 コメント​/Other​/Rangeまとめ編集

お名前:

*1 要素が参照渡しでアドレスの取得可能

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード印刷に適した表示   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom Powered by xpWiki
Counter: 2043, today: 2, yesterday: 2
初版日時: 2011-12-01 (木) 02:57:10
最終更新: 2011-12-01 (木) 02:57:10 (JST) (2089d) by ゲスト
メインメニュー

ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録

Menu