- お知らせ -
  • 当wikiのプログラムコードの表示を直してみました(ついでに長い行があると全体が下にぶっ飛ぶのも修正)。不具合があればBBSまでご連絡下さい。

D Edit

通常の使い方 Edit

二つ引数を指定するとindexも得られる分、Delphiより使い勝手がよい。
(実際、必要なときは多いので)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void main()
{
  static int a[] = [1111, 1234, 5678, 9999];

  printf("a[] = [");
  foreach (int value; a)
  {
    printf("%d, ", value);
  }
  printf("]\n");

  // index付き
  foreach (int i, int value; a)
  {
    printf("a[%d] = %d\n", i, value);
  }
}

出力結果

a[] = [1111, 1234, 5678, 9999, ]
a[0] = 1111
a[1] = 1234
a[2] = 5678
a[3] = 9999

クラスに対応させる Edit

opApplyを定義することで、構造体やクラスもforeach対応にできる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Foo
{
  static int array[] = [1111, 1234, 5678, 9999];

  int opApply(int delegate(inout int) dg)
  {
    int result = 0;
    for (int i = 0; i < array.length; i++) {
      result = dg(array[i]);
      if (result)
        break;
    }
    return result;
  }
}

void main()
{
  Foo foo = new Foo;
  foreach(int value; foo)
    printf("%d\n", value);
}

出力例

1111
1234
5678
9999

Delphi Edit

通常の使い方 Edit

for in doを使う。
Dと違い、要素の変更はできないっぽい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
program main;

{$APPTYPE CONSOLE}
const
  ArrayData: array [0..3] of Integer = (
    1111, 1234, 5678, 9999
  );
var
  i: Integer;
begin
  for i in ArrayData do
    Write(i, ', ')
  Writeln;
end.

出力結果

1111, 1234, 5678, 9999,

クラスに対応させる その1 Edit

for-in-doをクラスに対応させることもできる。
D言語ほど簡単でなく、ちょっと面倒。
オブジェクトを生成するので、多少パフォーマンスは不利かもしれない(←ゲーム野郎の言うことは気にしない方向で)。

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
57
58
59
60
61
62
63
64
65
66
67
program main;

{$APPTYPE CONSOLE}
uses SysUtils;
type
  TMyTest = class;

  TMyTestEnumerator = class
  private
    FMyTest: TMyTest;
    FIndex: Integer;
  public
    constructor Create(myTest: TMyTest);
    function GetCurrent: Integer;
    function MoveNext: Boolean;
    property Current: Integer read GetCurrent;
  end;

  TMyTest = class
  const
    ArrayData: array [0..3] of Integer = (
      1111, 1234, 5678, 9999
    );
  public
    function GetEnumerator: TMyTestEnumerator;
  end;

{ TMyTestEnumerator }

constructor TMyTestEnumerator.Create(myTest: TMyTest);
begin
  FMyTest := myTest;
  FIndex := -1;
end;

function TMyTestEnumerator.MoveNext: Boolean;
begin
  Result := (FIndex < High(FMyTest.ArrayData));
  if Result then
    Inc(FIndex);
end;

function TMyTestEnumerator.GetCurrent: Integer;
begin
  Result := FMyTest.ArrayData[FIndex]
end;

{ TMyTest }

function TMyTest.GetEnumerator: TMyTestEnumerator;
begin
  Result := TMyTestEnumerator.Create(Self);
end;

var
  MyTest: TMyTest;
  i: Integer;
begin
  MyTest := TMyTest.Create;
  try
    for i in MyTest do
      Write(i, ', ');
    Writeln;
  finally
    FreeAndNil(MyTest);
  end;
end.

出力結果

1111, 1234, 5678, 9999, 

クラスに対応させる その2 Edit

YTさん情報により、Enumratorをclassではなく、object(.NETはrecordか?)で定義できるとのこと。
これで、パフォーマンスの問題は解決なり。

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
57
58
59
60
61
62
63
64
65
66
67
program main;

{$APPTYPE CONSOLE}
uses SysUtils;
type
  TMyTest = class;

  TMyTestEnumerator = object
  private
    FMyTest: TMyTest;
    FIndex: Integer;
  public
    procedure Initialize(myTest: TMyTest);
    function GetCurrent: Integer;
    function MoveNext: Boolean;
    property Current: Integer read GetCurrent;
  end;

  TMyTest = class
  const
    ArrayData: array [0..3] of Integer = (
      1111, 1234, 5678, 9999
    );
  public
    function GetEnumerator: TMyTestEnumerator;
  end;

{ TMyTestEnumerator }

procedure TMyTestEnumerator.Initialize(myTest: TMyTest);
begin
  FMyTest := myTest;
  FIndex := -1;
end;

function TMyTestEnumerator.MoveNext: Boolean;
begin
  Result := (FIndex < High(FMyTest.ArrayData));
  if Result then
    Inc(FIndex);
end;

function TMyTestEnumerator.GetCurrent: Integer;
begin
  Result := FMyTest.ArrayData[FIndex]
end;

{ TMyTest }

function TMyTest.GetEnumerator: TMyTestEnumerator;
begin
  Result.Initialize(Self);
end;

var
  MyTest: TMyTest;
  i: Integer;
begin
  MyTest := TMyTest.Create;
  try
    for i in MyTest do
      Write(i, ', ');
    Writeln;
  finally
    FreeAndNil(MyTest);
  end;
end.

実行結果

1111, 1234, 5678, 9999, 

  • record(object)をEnumeratorにできますよ〜>パフォーマンス -- YT? 2005-07-15 21:21:27 (金)
  • な、なんですって〜知りませんでした。すげー。書き直さないとw -- TOBY 2005-07-15 23:37:32 (金)
  • Dでリンカエラーは、他のファイルと一緒にコンパイルしてたからでした。xyzzyで同ディレクトリ全部コンパイルするスクリプト書いてたの忘れてた。マヌケ・・・ -- TOBY 2005-07-18 14:30:33 (月)


Front page   Edit Freeze Diff Backup Upload Copy Rename Reload   New Pages Search Recent changes   Help   RSS of recent changes
Last-modified: 2006-05-02 Tue 17:41:41 JST (4222d)