Enumerable.vala 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. namespace Invercargill {
  2. public abstract class Enumerable<T> {
  3. public abstract Tracker<T> get_tracker();
  4. // Returns false if iteration was interrupted
  5. // Returns true if iteration reached natural end
  6. public virtual bool iterate_if(PredicateDelegate<T> handler) {
  7. var tracker = get_tracker();
  8. while(tracker.has_next()) {
  9. if(!handler(tracker.get_next())) {
  10. return false;
  11. }
  12. }
  13. return true;
  14. }
  15. public virtual void iterate(ItemDelegate<T> handler) {
  16. iterate_if(i => {
  17. handler(i);
  18. return true;
  19. });
  20. }
  21. public virtual Sequence<T> to_sequence() {
  22. var sequence = new Sequence<T>();
  23. iterate(i => sequence.add(i));
  24. return sequence;
  25. }
  26. public virtual Gee.Collection<T> to_collection() {
  27. var collection = new Gee.LinkedList<T>();
  28. iterate(i => collection.add(i));
  29. return collection;
  30. }
  31. public virtual Tracker<T> iterator() {
  32. return get_tracker();
  33. }
  34. public virtual T[] to_array() {
  35. return to_collection().to_array();
  36. }
  37. public virtual int count() {
  38. var count = 0;
  39. iterate(i => count++);
  40. return count;
  41. }
  42. public virtual bool any(PredicateDelegate<T> predicate) {
  43. var result = false;
  44. iterate_if(i => {
  45. if(predicate(i)) {
  46. result = true;
  47. return false;
  48. }
  49. return true;
  50. });
  51. return result;
  52. }
  53. public virtual bool all(PredicateDelegate<T> predicate) {
  54. return !any(i => !predicate(i));
  55. }
  56. public virtual bool no(PredicateDelegate<T> predicate) {
  57. return all(i => !predicate(i));
  58. }
  59. public virtual Enumerable<T> where(owned PredicateDelegate<T> predicate) {
  60. return new FilterQuery<T>(this, (owned)predicate);
  61. }
  62. public virtual Enumerable<Tout> select<Tout>(owned TransformDelegate<T, Tout> transform) {
  63. return new TransformQuery<T, Tout>(this, (owned)transform);
  64. }
  65. public virtual Enumerable<Tout> select_many<Tout>(owned TransformDelegate<T, Enumerable<Tout>> transform) {
  66. return new MergeQuery<Tout>(select((owned)transform));
  67. }
  68. public virtual Enumerable<T> sort(owned CompareDelegate<T> compare) {
  69. return new SortQuery<T>(this, (owned)compare);
  70. }
  71. public virtual Enumerable<T> concat(Enumerable<T> other) {
  72. return new ConcatEnumerable<T>(this, other);
  73. }
  74. public virtual Enumerable<T> take(int count) {
  75. return new TakeQuery<T>(this, count);
  76. }
  77. public virtual Enumerable<T> skip(int count) {
  78. return new SkipQuery<T>(this, count);
  79. }
  80. public virtual Enumerable<Tout> parallel<Tout>(owned TransformDelegate<T, Tout> transform, uint workers = 0) {
  81. var actual_workers = workers;
  82. if(actual_workers < 1) {
  83. actual_workers = get_num_processors();
  84. }
  85. return new ParallelQuery<T, Tout>(this, (owned)transform, (int)actual_workers);
  86. }
  87. public virtual Tout aggrigate<Tout>(Tout initial, AggrigateDelegate<Tout, T> aggrigate_func) {
  88. var aggrigate = initial;
  89. iterate(i => {
  90. aggrigate = aggrigate_func(aggrigate, i);
  91. });
  92. return aggrigate;
  93. }
  94. public virtual bool contains(T item) {
  95. return any(i => i == item);
  96. }
  97. public virtual Enumerable<Pair<T, Tother>> pair<Tother>(Enumerable<Tother> other) {
  98. return new PairEnumerable<T, Tother>(this, other);
  99. }
  100. public virtual Enumerable<T> zip(Enumerable<T> other) {
  101. return new ZipperEnumerable<T>(this, other);
  102. }
  103. public virtual Enumerable<Tout> fork<Tout>(owned TransformDelegate<T, Tout> fork1, owned TransformDelegate<T, Tout> fork2) {
  104. var seq = to_sequence();
  105. return seq.select<Tout>((owned)fork1).zip(seq.select<Tout>((owned)fork2));
  106. }
  107. public virtual Enumerable<Tout> fork_many<Tout>(owned TransformDelegate<T, Enumerable<Tout>> fork1, owned TransformDelegate<T, Enumerable<Tout>> fork2) {
  108. return new MergeQuery<Tout>(fork((owned)fork1, (owned)fork2));
  109. }
  110. public virtual bool matches(Enumerable<T> other, EqualityDelegate<T> equals) {
  111. return pair(other).all(p => equals(p.value1, p.value2));
  112. }
  113. public virtual Enumerable<T> with(T item) {
  114. var seq = new Sequence<T>();
  115. seq.add(item);
  116. return concat(seq);
  117. }
  118. public virtual T first() throws SequenceError {
  119. var tracker = get_tracker();
  120. if(tracker.has_next()) {
  121. return tracker.get_next();
  122. }
  123. throw new SequenceError.NO_ELEMENTS("The sequence contains no elements");
  124. }
  125. public virtual T? first_or_default() {
  126. var tracker = get_tracker();
  127. if(tracker.has_next()) {
  128. return tracker.get_next();
  129. }
  130. return null;
  131. }
  132. public virtual T single() throws SequenceError {
  133. var tracker = get_tracker();
  134. if(tracker.has_next()) {
  135. var item = tracker.get_next();
  136. if(tracker.has_next()) {
  137. throw new SequenceError.MULTUPLE_ELEMENTS("The sequence contains more than one element");
  138. }
  139. return item;
  140. }
  141. throw new SequenceError.NO_ELEMENTS("The sequence contains no elements");
  142. }
  143. public virtual T single_or_default() throws SequenceError {
  144. var tracker = get_tracker();
  145. if(tracker.has_next()) {
  146. var item = tracker.get_next();
  147. if(tracker.has_next()) {
  148. throw new SequenceError.MULTUPLE_ELEMENTS("The sequence contains more than one element");
  149. }
  150. return item;
  151. }
  152. return null;
  153. }
  154. public virtual string to_string(TransformDelegate<T, string> stringifier, string seperator = "") {
  155. bool is_first = true;
  156. return aggrigate<string>("", (s, v) => {
  157. if(is_first) {
  158. is_first = false;
  159. return stringifier(v);
  160. }
  161. return s + seperator + stringifier(v);
  162. });
  163. }
  164. }
  165. }