EnumerableOperations.vala 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. using Astralis;
  2. using Invercargill;
  3. using Invercargill.DataStructures;
  4. /**
  5. * EnumerableOperations Example
  6. *
  7. * Demonstrates various LINQ-like operations available in Invercargill Enumerable.
  8. * This example shows filtering, mapping, grouping, and aggregation operations.
  9. */
  10. // Root handler
  11. class RootEndpoint : Object, Endpoint {
  12. public string route { get { return "/"; } }
  13. public Method[] methods { owned get { return { Method.GET }; } }
  14. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  15. return new HttpStringResult("""Enumerable Operations Demo
  16. This example demonstrates various LINQ-like operations available in Invercargill Enumerable:
  17. Endpoints:
  18. GET /filter - Filtering examples
  19. GET /map - Mapping/Projection examples
  20. GET /group-by - Grouping examples
  21. GET /aggregate - Aggregation examples
  22. GET /sort - Sorting examples
  23. GET /set-operations - Set operations (union, intersection, etc.)
  24. GET /advanced - Advanced operations (zip, partition, etc.)
  25. """);
  26. }
  27. }
  28. // Filtering examples
  29. class FilterEndpoint : Object, Endpoint {
  30. public string route { get { return "/filter"; } }
  31. public Method[] methods { owned get { return { Method.GET }; } }
  32. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  33. var numbers = Wrap.array<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
  34. var parts = new Series<string>();
  35. parts.add_start("Original: ");
  36. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  37. parts.add_start("\n\n");
  38. // Filter even numbers
  39. var even = numbers.as_enumerable()
  40. .where(n => n % 2 == 0);
  41. parts.add_start("Even numbers: ");
  42. parts.add_start(enumerable_int_to_string(even));
  43. parts.add_start("\n");
  44. // Filter odd numbers
  45. var odd = numbers.as_enumerable()
  46. .where(n => n % 2 != 0);
  47. parts.add_start("Odd numbers: ");
  48. parts.add_start(enumerable_int_to_string(odd));
  49. parts.add_start("\n");
  50. // Filter numbers greater than 5
  51. var greater_than_5 = numbers.as_enumerable()
  52. .where(n => n > 5);
  53. parts.add_start("Greater than 5: ");
  54. parts.add_start(enumerable_int_to_string(greater_than_5));
  55. parts.add_start("\n\n");
  56. // Chained filters
  57. var filtered = numbers.as_enumerable()
  58. .where(n => n > 3)
  59. .where(n => n < 8);
  60. parts.add_start("Between 3 and 8: ");
  61. parts.add_start(enumerable_int_to_string(filtered));
  62. var result = parts.to_immutable_buffer()
  63. .aggregate<string>("", (acc, s) => acc + s);
  64. return new HttpStringResult(result);
  65. }
  66. }
  67. // Mapping/Projection examples
  68. class MapEndpoint : Object, Endpoint {
  69. public string route { get { return "/map"; } }
  70. public Method[] methods { owned get { return { Method.GET }; } }
  71. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  72. var numbers = Wrap.array<int>({1, 2, 3, 4, 5});
  73. var parts = new Series<string>();
  74. parts.add_start("Original: ");
  75. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  76. parts.add_start("\n\n");
  77. // Square each number
  78. var squared = numbers.as_enumerable()
  79. .select<int>(n => n * n);
  80. parts.add_start("Squared: ");
  81. parts.add_start(enumerable_int_to_string(squared));
  82. parts.add_start("\n");
  83. // Double each number
  84. var doubled = numbers.as_enumerable()
  85. .select<int>(n => n * 2);
  86. parts.add_start("Doubled: ");
  87. parts.add_start(enumerable_int_to_string(doubled));
  88. parts.add_start("\n");
  89. // Convert to string
  90. var as_strings = numbers.as_enumerable()
  91. .select<string>(n => n.to_string());
  92. parts.add_start("As strings: ");
  93. parts.add_start(enumerable_string_to_string(as_strings));
  94. parts.add_start("\n\n");
  95. // With index
  96. var with_index = numbers.as_enumerable()
  97. .with_positions()
  98. .select<string>(pair => @"$(pair.item) at index $(pair.position)");
  99. parts.add_start("With index: ");
  100. parts.add_start(enumerable_string_to_string(with_index));
  101. var result = parts.to_immutable_buffer()
  102. .aggregate<string>("", (acc, s) => acc + s);
  103. return new HttpStringResult(result);
  104. }
  105. }
  106. // Grouping examples
  107. class GroupByEndpoint : Object, Endpoint {
  108. public string route { get { return "/group-by"; } }
  109. public Method[] methods { owned get { return { Method.GET }; } }
  110. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  111. var words = Wrap.array<string>({
  112. "apple", "banana", "cherry", "apricot",
  113. "blueberry", "blackberry", "coconut"
  114. });
  115. var parts = new Series<string>();
  116. parts.add_start("Words: ");
  117. parts.add_start(enumerable_string_to_string(words.as_enumerable()));
  118. parts.add_start("\n\n");
  119. // Group by first letter
  120. var grouped = words.as_enumerable()
  121. .group_by<string>(w => w.get_char(0).to_string());
  122. parts.add_start("Grouped by first letter:\n");
  123. grouped.iterate((grouping) => {
  124. parts.add_start(@" $(grouping.key): ");
  125. parts.add_start(enumerable_string_to_string(grouping.to_immutable_buffer()));
  126. parts.add_start("\n");
  127. });
  128. var result = parts.to_immutable_buffer()
  129. .aggregate<string>("", (acc, s) => acc + s);
  130. return new HttpStringResult(result);
  131. }
  132. }
  133. // Aggregation examples
  134. class AggregateEndpoint : Object, Endpoint {
  135. public string route { get { return "/aggregate"; } }
  136. public Method[] methods { owned get { return { Method.GET }; } }
  137. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  138. var numbers = Wrap.array<int>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
  139. var parts = new Series<string>();
  140. parts.add_start("Numbers: ");
  141. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  142. parts.add_start("\n\n");
  143. // Count
  144. var count = numbers.as_enumerable().count();
  145. parts.add_start(@"Count: $count\n");
  146. // Sum using aggregate
  147. var sum = numbers.as_enumerable()
  148. .aggregate<int>(0, (acc, n) => acc + n);
  149. parts.add_start(@"Sum: $sum\n");
  150. // Average
  151. var avg = (double)sum / count;
  152. parts.add_start(@"Average: $avg\n");
  153. // Min
  154. var min = numbers.as_enumerable().min(n => n);
  155. parts.add_start(@"Min: $min\n");
  156. // Max
  157. var max = numbers.as_enumerable().max(n => n);
  158. parts.add_start(@"Max: $max\n");
  159. // First
  160. var first = numbers.as_enumerable().first();
  161. parts.add_start(@"First: $first\n");
  162. // Last
  163. var last = numbers.as_enumerable().last();
  164. parts.add_start(@"Last: $last\n");
  165. var result = parts.to_immutable_buffer()
  166. .aggregate<string>("", (acc, s) => acc + s);
  167. return new HttpStringResult(result);
  168. }
  169. }
  170. // Sorting examples
  171. class SortEndpoint : Object, Endpoint {
  172. public string route { get { return "/sort"; } }
  173. public Method[] methods { owned get { return { Method.GET }; } }
  174. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  175. var numbers = Wrap.array<int>({5, 2, 8, 1, 9, 3, 7, 4, 6, 10});
  176. var parts = new Series<string>();
  177. parts.add_start("Original: ");
  178. parts.add_start(enumerable_int_to_string(numbers.as_enumerable()));
  179. parts.add_start("\n\n");
  180. // Sort ascending
  181. var sorted_asc = numbers.as_enumerable()
  182. .order_by<int>(n => n);
  183. parts.add_start("Ascending: ");
  184. parts.add_start(enumerable_int_to_string(sorted_asc));
  185. parts.add_start("\n");
  186. // Sort descending
  187. var sorted_desc = numbers.as_enumerable()
  188. .order_by_descending<int>(n => n);
  189. parts.add_start("Descending: ");
  190. parts.add_start(enumerable_int_to_string(sorted_desc));
  191. var result = parts.to_immutable_buffer()
  192. .aggregate<string>("", (acc, s) => acc + s);
  193. return new HttpStringResult(result);
  194. }
  195. }
  196. // Set operations
  197. class SetOperationsEndpoint : Object, Endpoint {
  198. public string route { get { return "/set-operations"; } }
  199. public Method[] methods { owned get { return { Method.GET }; } }
  200. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  201. var set1 = Wrap.array<int>({1, 2, 3, 4, 5});
  202. var set2 = Wrap.array<int>({4, 5, 6, 7, 8});
  203. var parts = new Series<string>();
  204. parts.add_start("Set 1: ");
  205. parts.add_start(enumerable_int_to_string(set1.as_enumerable()));
  206. parts.add_start("\n");
  207. parts.add_start("Set 2: ");
  208. parts.add_start(enumerable_int_to_string(set2.as_enumerable()));
  209. parts.add_start("\n\n");
  210. // Union (concat)
  211. var union = set1.as_enumerable().concat(set2.as_enumerable());
  212. parts.add_start("Union: ");
  213. parts.add_start(enumerable_int_to_string(union));
  214. parts.add_start("\n");
  215. // Common (intersection)
  216. var common = set1.as_enumerable().common(set2.as_enumerable());
  217. parts.add_start("Common: ");
  218. parts.add_start(enumerable_int_to_string(common));
  219. parts.add_start("\n");
  220. // Non-common (difference)
  221. var diff = set1.as_enumerable().non_common(set2.as_enumerable());
  222. parts.add_start("In set1 but not set2: ");
  223. parts.add_start(enumerable_int_to_string(diff));
  224. var result = parts.to_immutable_buffer()
  225. .aggregate<string>("", (acc, s) => acc + s);
  226. return new HttpStringResult(result);
  227. }
  228. }
  229. // Advanced operations
  230. class AdvancedEndpoint : Object, Endpoint {
  231. public string route { get { return "/advanced"; } }
  232. public Method[] methods { owned get { return { Method.GET }; } }
  233. public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error {
  234. var numbers = Wrap.array<int>({1, 2, 3, 4, 5});
  235. var parts = new Series<string>();
  236. // Take
  237. var taken = numbers.as_enumerable().take(3);
  238. parts.add_start("Take 3: ");
  239. parts.add_start(enumerable_int_to_string(taken));
  240. parts.add_start("\n");
  241. // Skip
  242. var skipped = numbers.as_enumerable().skip(2);
  243. parts.add_start("Skip 2: ");
  244. parts.add_start(enumerable_int_to_string(skipped));
  245. parts.add_start("\n");
  246. // Distinct
  247. var with_dupes = Wrap.array<int>({1, 2, 2, 3, 3, 3, 4});
  248. var distinct = with_dupes.as_enumerable().distinct();
  249. parts.add_start("Distinct from {1,2,2,3,3,3,4}: ");
  250. parts.add_start(enumerable_int_to_string(distinct));
  251. parts.add_start("\n");
  252. // Reverse
  253. var reversed = numbers.as_enumerable().reverse();
  254. parts.add_start("Reversed: ");
  255. parts.add_start(enumerable_int_to_string(reversed));
  256. var result = parts.to_immutable_buffer()
  257. .aggregate<string>("", (acc, s) => acc + s);
  258. return new HttpStringResult(result);
  259. }
  260. }
  261. void main() {
  262. var router = new EndpointRouter()
  263. .add_endpoint(new RootEndpoint())
  264. .add_endpoint(new FilterEndpoint())
  265. .add_endpoint(new MapEndpoint())
  266. .add_endpoint(new GroupByEndpoint())
  267. .add_endpoint(new AggregateEndpoint())
  268. .add_endpoint(new SortEndpoint())
  269. .add_endpoint(new SetOperationsEndpoint())
  270. .add_endpoint(new AdvancedEndpoint());
  271. var pipeline = new Pipeline()
  272. .add_component(router);
  273. var server = new Server(8087, pipeline);
  274. print("Enumerable Operations Demo Server running on port 8087\n");
  275. print("Try these endpoints:\n");
  276. print(" - http://localhost:8087/\n");
  277. print(" - http://localhost:8087/filter\n");
  278. print(" - http://localhost:8087/map\n");
  279. print(" - http://localhost:8087/group-by\n");
  280. print(" - http://localhost:8087/aggregate\n");
  281. print(" - http://localhost:8087/sort\n");
  282. print(" - http://localhost:8087/set-operations\n");
  283. print(" - http://localhost:8087/advanced\n");
  284. server.run();
  285. }
  286. // Helper functions
  287. string enumerable_int_to_string(Enumerable<int> enumerable) {
  288. return enumerable.to_immutable_buffer()
  289. .aggregate<string>("[", (acc, n) => {
  290. if (acc == "[") return acc + n.to_string();
  291. return acc + ", " + n.to_string();
  292. }) + "]";
  293. }
  294. string enumerable_string_to_string(Enumerable<string> enumerable) {
  295. return enumerable.to_immutable_buffer()
  296. .aggregate<string>("[", (acc, s) => {
  297. if (acc == "[") return acc + "\"" + s + "\"";
  298. return acc + ", \"" + s + "\"";
  299. }) + "]";
  300. }