summaryrefslogtreecommitdiff
path: root/sources/scala/Iterator.scala
blob: 25a1c813080ce809169f1b0f988919e03ee35862 (plain) (blame)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package scala;

trait Iterator[a] {
  def hasNext: Boolean;
  def next: a;

  def foreach(f: a => Unit): Unit =
    while (hasNext) { f(next) }

  def take(n: Int) = new Iterator[a] {
    var remaining = n;
    def hasNext = remaining > 0 && Iterator.this.hasNext;
    def next: a =
      if (hasNext) { remaining = remaining - 1; Iterator.this.next }
      else error("next on empty iterator");
  }

  def drop(n: Int): Iterator[a] = if (n > 0) { next; drop(n - 1); } else this;

  def map[b](f: a => b): Iterator[b] = new Iterator[b] {
    def hasNext = Iterator.this.hasNext;
    def next = f(Iterator.this.next)
  }

  def flatMap[b](f: a => Iterator[b]): Iterator[b] = new Iterator[b] {
    private var cur: Iterator[b] = Iterator.empty;
    def hasNext: Boolean =
      if (cur.hasNext) true
      else if (Iterator.this.hasNext) { cur = f(Iterator.this.next); hasNext }
      else false;
    def next: b =
      if (cur.hasNext) cur.next
      else if (Iterator.this.hasNext) { cur = f(Iterator.this.next); next }
      else error("next on empty iterator");
  }

  def filter(p: a => Boolean): Iterator[a] = new BufferedIterator[a] {
    private val source =
      Iterator.this.buffered;
    private def skip: Unit =
      while (source.hasNext && !p(source.head)) { source.next; () }
    def hasNext: Boolean =
      { skip; source.hasNext }
    def next: a =
      { skip; source.next }
    def head: a =
      { skip; source.head; }
  }

  def zip[b](that: Iterator[b]) = new Iterator[Pair[a, b]] {
    def hasNext = Iterator.this.hasNext && that.hasNext;
    def next = Pair(Iterator.this.next, that.next);
  }

  def buffered: BufferedIterator[a] = new BufferedIterator[a] {
    private var hd: a = _;
    private var ahead: Boolean = false;
    def head: a = {
      if (!ahead) { hd = Iterator.this.next; ahead = true }
      hd
    }
    def next: a =
      if (ahead) { ahead = false; hd }
      else head;
    def hasNext: Boolean =
      ahead || Iterator.this.hasNext;
    override def buffered: BufferedIterator[a] = this;
  }
}

object Iterator {

  def empty[a] = new Iterator[a] {
    def hasNext = false;
    def next: a = error("next on empty iterator");
  }

  def fromArray[a](xs: Array[a]) = new Iterator[a] {
    private var i = 0;
    def hasNext: Boolean =
      i < xs.length;
    def next: a =
      if (i < xs.length) { val x = xs(i) ; i = i + 1 ; x }
      else error("next on empty iterator");
  }

  def range(lo: Int, hi: Int) = new Iterator[Int] {
    private var i = 0;
    def hasNext: Boolean =
      i <= hi;
    def next: Int =
      if (i <= hi) { i = i + 1 ; i - 1 }
      else error("next on empty iterator");
  }

  def from(lo: Int) = new Iterator[Int] {
    private var i = 0;
    def hasNext: Boolean =
      true;
    def next: Int =
      { i = i + 1 ; i - 1 }
  }
}