Enumerable.vala 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. namespace Invercargill {
  2. public abstract class Enumerable<T> : Object {
  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 = (i) => true) {
  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 = (i) => true) {
  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> cast<Tout>() {
  81. return select<Tout>(i => (Tout)i);
  82. }
  83. public virtual Enumerable<Tout> parallel_select<Tout>(owned TransformDelegate<T, Tout> transform, uint workers = 0) {
  84. var actual_workers = workers;
  85. if(actual_workers < 1) {
  86. actual_workers = get_num_processors();
  87. }
  88. return new ParallelQuery<T, Tout>(this, (owned)transform, (int)actual_workers);
  89. }
  90. public virtual int parallel_iterate(ItemDelegate<T> handler, uint workers = 0) {
  91. return parallel_select<T>(i => {
  92. handler(i);
  93. return i;
  94. }, workers)
  95. .count();
  96. }
  97. public virtual Enumerable<SelectionContext<T, Tout>> contextualised_select<Tout>(owned TransformDelegate<T, Tout> transform) {
  98. return new TransformQuery<T, SelectionContext<T, Tout>>(this, (i) => new SelectionContext<T, Tout>() {
  99. origin = i,
  100. result = transform(i)
  101. });
  102. }
  103. public virtual Tout aggrigate<Tout>(Tout initial, AggrigateDelegate<Tout, T> aggrigate_func) {
  104. var aggrigate = initial;
  105. iterate(i => {
  106. aggrigate = aggrigate_func(aggrigate, i);
  107. });
  108. return aggrigate;
  109. }
  110. public virtual bool contains(T item) {
  111. return any(i => i == item);
  112. }
  113. public virtual Enumerable<Pair<T, Tother>> pair<Tother>(Enumerable<Tother> other) {
  114. return new PairEnumerable<T, Tother>(this, other);
  115. }
  116. public virtual Enumerable<T> zip(Enumerable<T> other) {
  117. return new ZipperEnumerable<T>(this, other);
  118. }
  119. public virtual Enumerable<Tout> fork<Tout>(owned TransformDelegate<T, Tout> fork1, owned TransformDelegate<T, Tout> fork2) {
  120. var seq = to_sequence();
  121. return seq.select<Tout>((owned)fork1).zip(seq.select<Tout>((owned)fork2));
  122. }
  123. public virtual Enumerable<Tout> fork_many<Tout>(owned TransformDelegate<T, Enumerable<Tout>> fork1, owned TransformDelegate<T, Enumerable<Tout>> fork2) {
  124. return new MergeQuery<Tout>(fork((owned)fork1, (owned)fork2));
  125. }
  126. public virtual bool matches(Enumerable<T> other, EqualityDelegate<T> equals) {
  127. return pair(other).all(p => equals(p.value1, p.value2));
  128. }
  129. public virtual Enumerable<T> with(T item) {
  130. var seq = new Sequence<T>();
  131. seq.add(item);
  132. return concat(seq);
  133. }
  134. public virtual T first(owned PredicateDelegate<T>? predicate = null) throws SequenceError {
  135. var tracker = predicate == null ? get_tracker() : where((owned)predicate).get_tracker();
  136. if(tracker.has_next()) {
  137. return tracker.get_next();
  138. }
  139. throw new SequenceError.NO_ELEMENTS("The sequence contains no elements");
  140. }
  141. public virtual T? first_or_default(owned PredicateDelegate<T>? predicate = null) {
  142. var tracker = predicate == null ? get_tracker() : where((owned)predicate).get_tracker();
  143. if(tracker.has_next()) {
  144. return tracker.get_next();
  145. }
  146. return null;
  147. }
  148. public virtual T single(owned PredicateDelegate<T>? predicate = null) throws SequenceError {
  149. var tracker = predicate == null ? get_tracker() : where((owned)predicate).get_tracker();
  150. if(tracker.has_next()) {
  151. var item = tracker.get_next();
  152. if(tracker.has_next()) {
  153. throw new SequenceError.MULTUPLE_ELEMENTS("The sequence contains more than one element");
  154. }
  155. return item;
  156. }
  157. throw new SequenceError.NO_ELEMENTS("The sequence contains no elements");
  158. }
  159. public virtual T single_or_default(owned PredicateDelegate<T>? predicate = null) throws SequenceError {
  160. var tracker = predicate == null ? get_tracker() : where((owned)predicate).get_tracker();
  161. if(tracker.has_next()) {
  162. var item = tracker.get_next();
  163. if(tracker.has_next()) {
  164. throw new SequenceError.MULTUPLE_ELEMENTS("The sequence contains more than one element");
  165. }
  166. return item;
  167. }
  168. return null;
  169. }
  170. public virtual string to_string(TransformDelegate<T, string> stringifier, string seperator = "") {
  171. bool is_first = true;
  172. return aggrigate<string>("", (s, v) => {
  173. if(is_first) {
  174. is_first = false;
  175. return stringifier(v);
  176. }
  177. return s + seperator + stringifier(v);
  178. });
  179. }
  180. public virtual Object[] to_object_array() throws SequenceError {
  181. if(!typeof(T).is_object()) {
  182. throw new SequenceError.INVALID_TYPE("Can only make an object array of an Enumerable<T> where T is derrived from GLib.Object");
  183. }
  184. return select<Object>(i => (Object)i).to_array();
  185. }
  186. }
  187. }