Skip to main content

windjammer_runtime/
collections.rs

1//! Collection utilities
2//!
3//! Windjammer's `std::collections` module provides ergonomic functional
4//! programming methods that work directly on collections without requiring
5//! explicit `.iter()` and `.collect()` chains.
6//!
7//! # Examples
8//! ```windjammer
9//! use std::collections::*
10//!
11//! let numbers = vec![1, 2, 3, 4, 5]
12//! let doubled = map(numbers, |x| x * 2)           // [2, 4, 6, 8, 10]
13//! let evens = filter(numbers, |x| x % 2 == 0)     // [2, 4]
14//! let sum = reduce(numbers, 0, |acc, x| acc + x)  // 15
15//! ```
16
17// Re-export standard collections for public use
18pub use std::collections::HashMap;
19pub use std::collections::HashSet;
20pub use std::collections::VecDeque;
21
22// ============================================================================
23// FUNCTIONAL PROGRAMMING METHODS
24// ============================================================================
25
26/// Transform each element of a collection
27///
28/// # Example
29/// ```windjammer
30/// let numbers = vec![1, 2, 3]
31/// let doubled = map(numbers, |x| x * 2)  // [2, 4, 6]
32/// ```
33pub fn map<T, R, F>(vec: Vec<T>, f: F) -> Vec<R>
34where
35    F: FnMut(T) -> R,
36{
37    vec.into_iter().map(f).collect()
38}
39
40/// Keep only elements that satisfy the predicate
41///
42/// # Example
43/// ```windjammer
44/// let numbers = vec![1, 2, 3, 4, 5]
45/// let evens = filter(numbers, |x| x % 2 == 0)  // [2, 4]
46/// ```
47pub fn filter<T, F>(vec: Vec<T>, f: F) -> Vec<T>
48where
49    F: FnMut(&T) -> bool,
50{
51    vec.into_iter().filter(f).collect()
52}
53
54/// Reduce a collection to a single value
55///
56/// # Example
57/// ```windjammer
58/// let numbers = vec![1, 2, 3, 4, 5]
59/// let sum = reduce(numbers, 0, |acc, x| acc + x)  // 15
60/// ```
61pub fn reduce<T, R, F>(vec: Vec<T>, initial: R, f: F) -> R
62where
63    F: FnMut(R, T) -> R,
64{
65    vec.into_iter().fold(initial, f)
66}
67
68/// Alias for reduce (fold)
69pub fn fold<T, R, F>(vec: Vec<T>, initial: R, f: F) -> R
70where
71    F: FnMut(R, T) -> R,
72{
73    reduce(vec, initial, f)
74}
75
76/// Find the first element that satisfies the predicate
77///
78/// # Example
79/// ```windjammer
80/// let numbers = vec![1, 2, 3, 4, 5]
81/// let first_even = find(numbers, |x| x % 2 == 0)  // Some(2)
82/// ```
83pub fn find<T, F>(vec: Vec<T>, mut f: F) -> Option<T>
84where
85    F: FnMut(&T) -> bool,
86{
87    vec.into_iter().find(|x| f(x))
88}
89
90/// Check if any element satisfies the predicate
91///
92/// # Example
93/// ```windjammer
94/// let numbers = vec![1, 2, 3, 4, 5]
95/// let has_even = any(numbers, |x| x % 2 == 0)  // true
96/// ```
97pub fn any<T, F>(vec: Vec<T>, mut f: F) -> bool
98where
99    F: FnMut(&T) -> bool,
100{
101    vec.into_iter().any(|x| f(&x))
102}
103
104/// Check if all elements satisfy the predicate
105///
106/// # Example
107/// ```windjammer
108/// let numbers = vec![2, 4, 6, 8]
109/// let all_even = all(numbers, |x| x % 2 == 0)  // true
110/// ```
111pub fn all<T, F>(vec: Vec<T>, mut f: F) -> bool
112where
113    F: FnMut(&T) -> bool,
114{
115    vec.into_iter().all(|x| f(&x))
116}
117
118/// Check if no elements satisfy the predicate
119///
120/// # Example
121/// ```windjammer
122/// let numbers = vec![1, 3, 5, 7]
123/// let no_even = none(numbers, |x| x % 2 == 0)  // true
124/// ```
125pub fn none<T, F>(vec: Vec<T>, f: F) -> bool
126where
127    F: FnMut(&T) -> bool,
128{
129    !any(vec, f)
130}
131
132/// Take the first n elements
133///
134/// # Example
135/// ```windjammer
136/// let numbers = vec![1, 2, 3, 4, 5]
137/// let first_three = take(numbers, 3)  // [1, 2, 3]
138/// ```
139pub fn take<T>(vec: Vec<T>, n: usize) -> Vec<T> {
140    vec.into_iter().take(n).collect()
141}
142
143/// Skip the first n elements
144///
145/// # Example
146/// ```windjammer
147/// let numbers = vec![1, 2, 3, 4, 5]
148/// let last_two = skip(numbers, 3)  // [4, 5]
149/// ```
150pub fn skip<T>(vec: Vec<T>, n: usize) -> Vec<T> {
151    vec.into_iter().skip(n).collect()
152}
153
154/// Take elements while predicate is true
155///
156/// # Example
157/// ```windjammer
158/// let numbers = vec![1, 2, 3, 4, 5]
159/// let small = take_while(numbers, |x| x < 4)  // [1, 2, 3]
160/// ```
161pub fn take_while<T, F>(vec: Vec<T>, f: F) -> Vec<T>
162where
163    F: FnMut(&T) -> bool,
164{
165    vec.into_iter().take_while(f).collect()
166}
167
168/// Skip elements while predicate is true
169///
170/// # Example
171/// ```windjammer
172/// let numbers = vec![1, 2, 3, 4, 5]
173/// let big = skip_while(numbers, |x| x < 3)  // [3, 4, 5]
174/// ```
175pub fn skip_while<T, F>(vec: Vec<T>, f: F) -> Vec<T>
176where
177    F: FnMut(&T) -> bool,
178{
179    vec.into_iter().skip_while(f).collect()
180}
181
182/// Flatten a nested collection
183///
184/// # Example
185/// ```windjammer
186/// let nested = vec![vec![1, 2], vec![3, 4], vec![5]]
187/// let flat = flatten(nested)  // [1, 2, 3, 4, 5]
188/// ```
189pub fn flatten<T>(vec: Vec<Vec<T>>) -> Vec<T> {
190    vec.into_iter().flatten().collect()
191}
192
193/// Map and flatten in one step
194///
195/// # Example
196/// ```windjammer
197/// let words = vec!["hello", "world"]
198/// let chars = flat_map(words, |s| s.chars().collect())
199/// ```
200pub fn flat_map<T, R, F>(vec: Vec<T>, f: F) -> Vec<R>
201where
202    F: FnMut(T) -> Vec<R>,
203{
204    vec.into_iter().flat_map(f).collect()
205}
206
207/// Zip two collections together
208///
209/// # Example
210/// ```windjammer
211/// let a = vec![1, 2, 3]
212/// let b = vec!["a", "b", "c"]
213/// let pairs = zip(a, b)  // [(1, "a"), (2, "b"), (3, "c")]
214/// ```
215pub fn zip<A, B>(a: Vec<A>, b: Vec<B>) -> Vec<(A, B)> {
216    a.into_iter().zip(b).collect()
217}
218
219/// Add indices to elements
220///
221/// # Example
222/// ```windjammer
223/// let items = vec!["a", "b", "c"]
224/// let indexed = enumerate(items)  // [(0, "a"), (1, "b"), (2, "c")]
225/// ```
226pub fn enumerate<T>(vec: Vec<T>) -> Vec<(usize, T)> {
227    vec.into_iter().enumerate().collect()
228}
229
230/// Concatenate two collections
231///
232/// # Example
233/// ```windjammer
234/// let a = vec![1, 2, 3]
235/// let b = vec![4, 5, 6]
236/// let both = chain(a, b)  // [1, 2, 3, 4, 5, 6]
237/// ```
238pub fn chain<T>(a: Vec<T>, b: Vec<T>) -> Vec<T> {
239    a.into_iter().chain(b).collect()
240}
241
242/// Partition elements by predicate
243///
244/// # Example
245/// ```windjammer
246/// let numbers = vec![1, 2, 3, 4, 5]
247/// let (evens, odds) = partition(numbers, |x| x % 2 == 0)
248/// // evens = [2, 4], odds = [1, 3, 5]
249/// ```
250pub fn partition<T, F>(vec: Vec<T>, mut f: F) -> (Vec<T>, Vec<T>)
251where
252    F: FnMut(&T) -> bool,
253{
254    vec.into_iter().partition(|x| f(x))
255}
256
257/// Group elements by key
258///
259/// # Example
260/// ```windjammer
261/// let words = vec!["apple", "ant", "banana", "bear"]
262/// let by_first = group_by(words, |s| s.chars().next().unwrap())
263/// // {'a': ["apple", "ant"], 'b': ["banana", "bear"]}
264/// ```
265pub fn group_by<T, K, F>(vec: Vec<T>, mut f: F) -> HashMap<K, Vec<T>>
266where
267    K: std::hash::Hash + Eq,
268    F: FnMut(&T) -> K,
269{
270    let mut result: HashMap<K, Vec<T>> = HashMap::new();
271    for item in vec {
272        let key = f(&item);
273        result.entry(key).or_default().push(item);
274    }
275    result
276}
277
278/// Count elements by key
279///
280/// # Example
281/// ```windjammer
282/// let items = vec!["a", "b", "a", "c", "a", "b"]
283/// let counts = count_by(items, |x| x)
284/// // {"a": 3, "b": 2, "c": 1}
285/// ```
286pub fn count_by<T, K, F>(vec: Vec<T>, mut f: F) -> HashMap<K, usize>
287where
288    K: std::hash::Hash + Eq,
289    F: FnMut(&T) -> K,
290{
291    let mut result: HashMap<K, usize> = HashMap::new();
292    for item in vec {
293        let key = f(&item);
294        *result.entry(key).or_default() += 1;
295    }
296    result
297}
298
299/// Sum all elements
300///
301/// # Example
302/// ```windjammer
303/// let numbers = vec![1, 2, 3, 4, 5]
304/// let total = sum(numbers)  // 15
305/// ```
306pub fn sum<T>(vec: Vec<T>) -> T
307where
308    T: std::iter::Sum,
309{
310    vec.into_iter().sum()
311}
312
313/// Product of all elements
314///
315/// # Example
316/// ```windjammer
317/// let numbers = vec![1, 2, 3, 4, 5]
318/// let total = product(numbers)  // 120
319/// ```
320pub fn product<T>(vec: Vec<T>) -> T
321where
322    T: std::iter::Product,
323{
324    vec.into_iter().product()
325}
326
327/// Find the minimum element
328///
329/// # Example
330/// ```windjammer
331/// let numbers = vec![3, 1, 4, 1, 5]
332/// let smallest = min(numbers)  // Some(1)
333/// ```
334pub fn min<T: Ord>(vec: Vec<T>) -> Option<T> {
335    vec.into_iter().min()
336}
337
338/// Find the maximum element
339///
340/// # Example
341/// ```windjammer
342/// let numbers = vec![3, 1, 4, 1, 5]
343/// let largest = max(numbers)  // Some(5)
344/// ```
345pub fn max<T: Ord>(vec: Vec<T>) -> Option<T> {
346    vec.into_iter().max()
347}
348
349/// Find minimum by key
350pub fn min_by<T, K, F>(vec: Vec<T>, mut f: F) -> Option<T>
351where
352    K: Ord,
353    F: FnMut(&T) -> K,
354{
355    vec.into_iter().min_by_key(|x| f(x))
356}
357
358/// Find maximum by key
359pub fn max_by<T, K, F>(vec: Vec<T>, mut f: F) -> Option<T>
360where
361    K: Ord,
362    F: FnMut(&T) -> K,
363{
364    vec.into_iter().max_by_key(|x| f(x))
365}
366
367/// Get first element
368///
369/// # Example
370/// ```windjammer
371/// let numbers = vec![1, 2, 3]
372/// let first = first(numbers)  // Some(1)
373/// ```
374pub fn first<T>(vec: Vec<T>) -> Option<T> {
375    vec.into_iter().next()
376}
377
378/// Get last element
379///
380/// # Example
381/// ```windjammer
382/// let numbers = vec![1, 2, 3]
383/// let last = last(numbers)  // Some(3)
384/// ```
385pub fn last<T>(vec: Vec<T>) -> Option<T> {
386    vec.into_iter().last()
387}
388
389/// Get nth element (0-indexed)
390///
391/// # Example
392/// ```windjammer
393/// let numbers = vec![1, 2, 3, 4, 5]
394/// let third = nth(numbers, 2)  // Some(3)
395/// ```
396pub fn nth<T>(vec: Vec<T>, n: usize) -> Option<T> {
397    vec.into_iter().nth(n)
398}
399
400/// Sort by key function
401///
402/// # Example
403/// ```windjammer
404/// let words = vec!["banana", "apple", "cherry"]
405/// let by_len = sort_by(words, |s| s.len())  // ["apple", "banana", "cherry"]
406/// ```
407pub fn sort_by<T, K, F>(mut vec: Vec<T>, mut f: F) -> Vec<T>
408where
409    K: Ord,
410    F: FnMut(&T) -> K,
411{
412    vec.sort_by_key(|x| f(x));
413    vec
414}
415
416/// Reverse iterator
417///
418/// # Example
419/// ```windjammer
420/// let numbers = vec![1, 2, 3]
421/// let rev = reversed(numbers)  // [3, 2, 1]
422/// ```
423pub fn reversed<T>(vec: Vec<T>) -> Vec<T> {
424    vec.into_iter().rev().collect()
425}
426
427/// Create a range of numbers
428///
429/// # Example
430/// ```windjammer
431/// let nums = range(1, 5)  // [1, 2, 3, 4]
432/// ```
433pub fn range(start: i32, end: i32) -> Vec<i32> {
434    (start..end).collect()
435}
436
437/// Create an inclusive range of numbers
438///
439/// # Example
440/// ```windjammer
441/// let nums = range_inclusive(1, 5)  // [1, 2, 3, 4, 5]
442/// ```
443pub fn range_inclusive(start: i32, end: i32) -> Vec<i32> {
444    (start..=end).collect()
445}
446
447/// Repeat a value n times
448///
449/// # Example
450/// ```windjammer
451/// let zeros = repeat(0, 5)  // [0, 0, 0, 0, 0]
452/// ```
453pub fn repeat<T: Clone>(value: T, n: usize) -> Vec<T> {
454    std::iter::repeat_n(value, n).collect()
455}
456
457// ============================================================================
458// COLLECTION HELPERS (existing functionality)
459// ============================================================================
460
461/// Create a new HashMap
462pub fn new_map<K, V>() -> HashMap<K, V>
463where
464    K: std::hash::Hash + Eq,
465{
466    HashMap::new()
467}
468
469/// Create a new HashSet
470pub fn new_set<T>() -> HashSet<T>
471where
472    T: std::hash::Hash + Eq,
473{
474    HashSet::new()
475}
476
477/// Create a new VecDeque
478pub fn new_deque<T>() -> VecDeque<T> {
479    VecDeque::new()
480}
481
482/// Check if slice contains element
483pub fn contains<T: PartialEq>(slice: &[T], item: &T) -> bool {
484    slice.contains(item)
485}
486
487/// Find index of element in slice
488pub fn index_of<T: PartialEq>(slice: &[T], item: &T) -> Option<usize> {
489    slice.iter().position(|x| x == item)
490}
491
492/// Reverse a vector (in-place style, returns new vec)
493pub fn reverse<T: Clone>(vec: &[T]) -> Vec<T> {
494    let mut result = vec.to_vec();
495    result.reverse();
496    result
497}
498
499/// Sort a vector (in-place style, returns new vec)
500pub fn sort<T: Clone + Ord>(vec: &[T]) -> Vec<T> {
501    let mut result = vec.to_vec();
502    result.sort();
503    result
504}
505
506/// Remove duplicates from vector
507pub fn unique<T: Clone + Eq + std::hash::Hash>(vec: &[T]) -> Vec<T> {
508    let set: HashSet<_> = vec.iter().cloned().collect();
509    set.into_iter().collect()
510}
511
512#[cfg(test)]
513mod tests {
514    use super::*;
515
516    // ========== FUNCTIONAL PROGRAMMING TESTS ==========
517
518    #[test]
519    fn test_map() {
520        let vec = vec![1, 2, 3];
521        let result = map(vec, |x| x * 2);
522        assert_eq!(result, vec![2, 4, 6]);
523    }
524
525    #[test]
526    fn test_filter() {
527        let vec = vec![1, 2, 3, 4, 5];
528        let result = filter(vec, |x| x % 2 == 0);
529        assert_eq!(result, vec![2, 4]);
530    }
531
532    #[test]
533    fn test_reduce() {
534        let vec = vec![1, 2, 3, 4, 5];
535        let result = reduce(vec, 0, |acc, x| acc + x);
536        assert_eq!(result, 15);
537    }
538
539    #[test]
540    fn test_fold() {
541        let vec = vec![1, 2, 3];
542        let result = fold(vec, String::new(), |acc, x| format!("{}{}", acc, x));
543        assert_eq!(result, "123");
544    }
545
546    #[test]
547    fn test_find() {
548        let vec = vec![1, 2, 3, 4, 5];
549        assert_eq!(find(vec.clone(), |x| *x > 3), Some(4));
550        assert_eq!(find(vec, |x| *x > 10), None);
551    }
552
553    #[test]
554    fn test_any() {
555        let vec = vec![1, 2, 3, 4, 5];
556        assert!(any(vec.clone(), |x| *x > 3));
557        assert!(!any(vec, |x| *x > 10));
558    }
559
560    #[test]
561    fn test_all() {
562        let vec = vec![2, 4, 6, 8];
563        assert!(all(vec.clone(), |x| *x % 2 == 0));
564        assert!(!all(vec, |x| *x > 5));
565    }
566
567    #[test]
568    fn test_none() {
569        let vec = vec![1, 3, 5, 7];
570        assert!(none(vec.clone(), |x| *x % 2 == 0));
571        assert!(!none(vec, |x| *x > 5));
572    }
573
574    #[test]
575    fn test_take() {
576        let vec = vec![1, 2, 3, 4, 5];
577        assert_eq!(take(vec, 3), vec![1, 2, 3]);
578    }
579
580    #[test]
581    fn test_skip() {
582        let vec = vec![1, 2, 3, 4, 5];
583        assert_eq!(skip(vec, 3), vec![4, 5]);
584    }
585
586    #[test]
587    fn test_take_while() {
588        let vec = vec![1, 2, 3, 4, 5];
589        assert_eq!(take_while(vec, |x| *x < 4), vec![1, 2, 3]);
590    }
591
592    #[test]
593    fn test_skip_while() {
594        let vec = vec![1, 2, 3, 4, 5];
595        assert_eq!(skip_while(vec, |x| *x < 3), vec![3, 4, 5]);
596    }
597
598    #[test]
599    fn test_flatten() {
600        let vec = vec![vec![1, 2], vec![3, 4], vec![5]];
601        assert_eq!(flatten(vec), vec![1, 2, 3, 4, 5]);
602    }
603
604    #[test]
605    fn test_flat_map() {
606        let vec = vec![1, 2, 3];
607        let result = flat_map(vec, |x| vec![x, x * 10]);
608        assert_eq!(result, vec![1, 10, 2, 20, 3, 30]);
609    }
610
611    #[test]
612    fn test_zip() {
613        let a = vec![1, 2, 3];
614        let b = vec!["a", "b", "c"];
615        assert_eq!(zip(a, b), vec![(1, "a"), (2, "b"), (3, "c")]);
616    }
617
618    #[test]
619    fn test_enumerate() {
620        let vec = vec!["a", "b", "c"];
621        assert_eq!(enumerate(vec), vec![(0, "a"), (1, "b"), (2, "c")]);
622    }
623
624    #[test]
625    fn test_chain() {
626        let a = vec![1, 2, 3];
627        let b = vec![4, 5, 6];
628        assert_eq!(chain(a, b), vec![1, 2, 3, 4, 5, 6]);
629    }
630
631    #[test]
632    fn test_partition() {
633        let vec = vec![1, 2, 3, 4, 5];
634        let (evens, odds) = partition(vec, |x| x % 2 == 0);
635        assert_eq!(evens, vec![2, 4]);
636        assert_eq!(odds, vec![1, 3, 5]);
637    }
638
639    #[test]
640    fn test_group_by() {
641        let vec = vec!["apple", "ant", "banana", "bear"];
642        let groups = group_by(vec, |s| s.chars().next().unwrap());
643        assert_eq!(groups.get(&'a').unwrap().len(), 2);
644        assert_eq!(groups.get(&'b').unwrap().len(), 2);
645    }
646
647    #[test]
648    fn test_count_by() {
649        let vec = vec!["a", "b", "a", "c", "a", "b"];
650        let counts = count_by(vec, |x| *x);
651        assert_eq!(counts.get(&"a"), Some(&3));
652        assert_eq!(counts.get(&"b"), Some(&2));
653        assert_eq!(counts.get(&"c"), Some(&1));
654    }
655
656    #[test]
657    fn test_sum() {
658        let vec = vec![1, 2, 3, 4, 5];
659        assert_eq!(sum(vec), 15);
660    }
661
662    #[test]
663    fn test_product() {
664        let vec = vec![1, 2, 3, 4, 5];
665        assert_eq!(product(vec), 120);
666    }
667
668    #[test]
669    fn test_min_max() {
670        let vec = vec![3, 1, 4, 1, 5];
671        assert_eq!(min(vec.clone()), Some(1));
672        assert_eq!(max(vec), Some(5));
673    }
674
675    #[test]
676    fn test_min_max_by() {
677        let vec = vec!["aa", "bbb", "c"];
678        assert_eq!(min_by(vec.clone(), |s| s.len()), Some("c"));
679        assert_eq!(max_by(vec, |s| s.len()), Some("bbb"));
680    }
681
682    #[test]
683    fn test_first_last() {
684        let vec = vec![1, 2, 3];
685        assert_eq!(first(vec.clone()), Some(1));
686        assert_eq!(last(vec), Some(3));
687    }
688
689    #[test]
690    fn test_nth() {
691        let vec = vec![1, 2, 3, 4, 5];
692        assert_eq!(nth(vec.clone(), 2), Some(3));
693        assert_eq!(nth(vec, 10), None);
694    }
695
696    #[test]
697    fn test_sort_by() {
698        let vec = vec!["banana", "apple", "cherry"];
699        let result = sort_by(vec, |s| s.len());
700        assert_eq!(result, vec!["apple", "banana", "cherry"]);
701    }
702
703    #[test]
704    fn test_reversed() {
705        let vec = vec![1, 2, 3];
706        assert_eq!(reversed(vec), vec![3, 2, 1]);
707    }
708
709    #[test]
710    fn test_range() {
711        assert_eq!(range(1, 5), vec![1, 2, 3, 4]);
712    }
713
714    #[test]
715    fn test_range_inclusive() {
716        assert_eq!(range_inclusive(1, 5), vec![1, 2, 3, 4, 5]);
717    }
718
719    #[test]
720    fn test_repeat() {
721        assert_eq!(repeat(0, 5), vec![0, 0, 0, 0, 0]);
722    }
723
724    // ========== COLLECTION HELPER TESTS ==========
725
726    #[test]
727    fn test_contains() {
728        let vec = vec![1, 2, 3, 4, 5];
729        assert!(contains(&vec, &3));
730        assert!(!contains(&vec, &10));
731    }
732
733    #[test]
734    fn test_index_of() {
735        let vec = vec!["a", "b", "c"];
736        assert_eq!(index_of(&vec, &"b"), Some(1));
737        assert_eq!(index_of(&vec, &"z"), None);
738    }
739
740    #[test]
741    fn test_reverse() {
742        let vec = vec![1, 2, 3];
743        assert_eq!(reverse(&vec), vec![3, 2, 1]);
744    }
745
746    #[test]
747    fn test_sort() {
748        let vec = vec![3, 1, 2];
749        assert_eq!(sort(&vec), vec![1, 2, 3]);
750    }
751
752    #[test]
753    fn test_unique() {
754        let vec = vec![1, 2, 2, 3, 3, 3];
755        let result = unique(&vec);
756        assert_eq!(result.len(), 3);
757        assert!(result.contains(&1));
758        assert!(result.contains(&2));
759        assert!(result.contains(&3));
760    }
761}