orx_parallel/result_use/par.rs
1#![allow(clippy::type_complexity)]
2
3use crate::infallible_use::fun::{UFnCloned, UFnCopied};
4use crate::infallible_use::{
5 FilMapOf, FilOf, FlatMapOf, FlattenOf, InsOf, MapOf, MappedOf, XapUse,
6};
7use crate::result_use::ParUseResultIter;
8use crate::result_use::par_core::ParUseResultCore;
9use crate::runner::ParRunner;
10use crate::sizes::{OneOne, SizePair};
11use crate::{ChunkSize, IterationOrder, NumThreads, ParExtend, Sum};
12use core::cmp::Ordering;
13use orx_concurrent_iter::ExactSizeConcurrentIter;
14
15/// Fallible parallel iterator with worker-local mutable state.
16///
17/// `ParUseResult` combines:
18/// - fallible processing (`Result`-based short-circuiting), and
19/// - mutable worker-local state (`&mut Use` passed to closures).
20///
21/// You can enter this mode from [`ParResult`](crate::ParResult) via
22/// [`use_new`](crate::ParResult::use_new),
23/// [`use_vec`](crate::ParResult::use_vec), or
24/// [`use_slice`](crate::ParResult::use_slice).
25///
26/// Similar to using `?`, this trait keeps pipeline logic focused on successful
27/// values while computation short-circuits to `Err(e)` when any element fails.
28///
29/// Related traits:
30/// - [`ParResult`](crate::ParResult) for `Result`-fallible pipelines without worker-local state,
31/// - [`ParUse`](crate::ParUse) for worker-local state in infallible pipelines.
32///
33/// # Examples
34///
35/// Reusing a per-worker buffer:
36///
37/// ```
38/// use core::fmt::Write;
39/// use orx_parallel::*;
40///
41/// let out: Result<Vec<usize>, _> = ["0", "1", "2", "3", "4", "5", "6", "7"]
42/// .into_par()
43/// .map(|s| s.parse::<usize>())
44/// .into_fallible()
45/// .use_new(|_| String::with_capacity(32))
46/// .map(|buffer, x| {
47/// buffer.clear();
48/// write!(buffer, "{x}").unwrap();
49/// buffer.parse::<usize>().unwrap()
50/// })
51/// .collect();
52///
53/// assert_eq!(out, Ok((0..8).collect::<Vec<_>>()));
54/// ```
55///
56/// Using RNG as mutable worker-local state:
57///
58/// ```
59/// use orx_parallel::*;
60/// use rand::prelude::*;
61/// use rand_chacha::ChaCha8Rng;
62///
63/// let out: Result<Vec<usize>, _> = ["0", "1", "2", "3", "4", "5", "6", "7"]
64/// .into_par()
65/// .map(|s| s.parse::<usize>())
66/// .into_fallible()
67/// .use_new(|thread_idx| ChaCha8Rng::seed_from_u64(100 + thread_idx as u64))
68/// .map(|rng, x| x + rng.random_range(0..10))
69/// .collect();
70///
71/// assert_eq!(out.as_ref().map(Vec::len), Ok(8));
72/// ```
73pub trait ParUseResult: Sized + ParUseResultCore {
74 // configuration
75
76 /// Replaces the current parallel runner with `runner`.
77 ///
78 /// # Examples
79 ///
80 /// ```
81 /// use orx_parallel::*;
82 ///
83 /// let par = ["1", "2", "3"]
84 /// .into_par()
85 /// .map(|s| s.parse::<usize>())
86 /// .into_fallible()
87 /// .use_new(|_| ());
88 ///
89 /// let par = par.runner(Runner::fixed());
90 ///
91 /// let out: Result<Vec<_>, _> = par.collect();
92 /// assert_eq!(out, Ok(vec![1, 2, 3]));
93 /// ```
94 fn runner<Q: ParRunner>(
95 self,
96 runner: Q,
97 ) -> impl ParUseResult<
98 Elem = Self::Elem,
99 Error = Self::Error,
100 Use = Self::Use,
101 Xap1 = Self::Xap1,
102 M = Self::M,
103 Xap2 = Self::Xap2,
104 Input = Self::Input,
105 Size = Self::Size,
106 >;
107
108 #[cfg(feature = "std")]
109 /// Wraps the current runner with diagnostics-enabled execution.
110 ///
111 /// # Examples
112 ///
113 /// ```
114 /// use orx_parallel::*;
115 ///
116 /// let par = ["1", "2", "3"]
117 /// .into_par()
118 /// .map(|s| s.parse::<usize>())
119 /// .into_fallible()
120 /// .use_new(|_| ());
121 ///
122 /// #[cfg(feature = "std")]
123 /// let par = par.runner_with_diagnostics();
124 ///
125 /// let out: Result<Vec<_>, _> = par.collect();
126 /// assert_eq!(out, Ok(vec![1, 2, 3]));
127 /// ```
128 fn runner_with_diagnostics(
129 self,
130 ) -> impl ParUseResult<
131 Elem = Self::Elem,
132 Error = Self::Error,
133 Use = Self::Use,
134 Xap1 = Self::Xap1,
135 M = Self::M,
136 Xap2 = Self::Xap2,
137 Input = Self::Input,
138 Size = Self::Size,
139 >;
140
141 /// Sets the maximum number of worker threads for this computation.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use orx_parallel::*;
147 ///
148 /// let out: Result<Vec<_>, _> = ["1", "2", "3", "4", "5"]
149 /// .into_par()
150 /// .map(|s| s.parse::<usize>())
151 /// .into_fallible()
152 /// .use_new(|_| ())
153 /// .num_threads(1)
154 /// .collect();
155 ///
156 /// assert_eq!(out, Ok(vec![1, 2, 3, 4, 5]));
157 /// ```
158 fn num_threads(self, num_threads: impl Into<NumThreads>) -> Self;
159
160 /// Sets chunk size used when pulling items from the concurrent input.
161 ///
162 /// # Examples
163 ///
164 /// ```
165 /// use orx_parallel::*;
166 ///
167 /// let out: Result<Vec<_>, _> = ["0", "1", "2", "3", "4", "5", "6", "7"]
168 /// .into_par()
169 /// .map(|s| s.parse::<usize>())
170 /// .into_fallible()
171 /// .use_new(|_| ())
172 /// .chunk_size(2)
173 /// .collect();
174 ///
175 /// assert_eq!(out, Ok((0..8).collect::<Vec<_>>()));
176 /// ```
177 fn chunk_size(self, chunk_size: impl Into<ChunkSize>) -> Self;
178
179 /// Sets iteration-order semantics for order-sensitive operations.
180 ///
181 /// # Examples
182 ///
183 /// ```
184 /// use orx_parallel::*;
185 ///
186 /// let ordered = (1..10_000)
187 /// .map(|x| x.to_string())
188 /// .collect::<Vec<_>>()
189 /// .into_par()
190 /// .map(|s| s.parse::<usize>())
191 /// .into_fallible()
192 /// .use_new(|_| ())
193 /// .iteration_order(IterationOrder::Ordered)
194 /// .find(|_, x| x % 3421 == 0);
195 ///
196 /// assert_eq!(ordered, Ok(Some(3421)));
197 /// ```
198 fn iteration_order(self, collect: IterationOrder) -> Self;
199
200 // kind transformations
201
202 /// Copies elements of a reference iterator on the success path.
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use orx_parallel::*;
208 ///
209 /// let data = vec![1, 2, 3];
210 /// let out: Result<Vec<_>, &'static str> = data
211 /// .par()
212 /// .map(Ok::<_, &'static str>)
213 /// .into_fallible()
214 /// .use_new(|_| ())
215 /// .copied()
216 /// .collect();
217 ///
218 /// assert_eq!(out, Ok(vec![1, 2, 3]));
219 /// ```
220 fn copied<'a, O>(
221 self,
222 ) -> impl ParUseResult<
223 Elem = O,
224 Error = Self::Error,
225 Use = Self::Use,
226 Xap1 = Self::Xap1,
227 M = Self::M,
228 Xap2 = MappedOf<Self::Xap2, UFnCopied<'a, Self::Use, O>>,
229 Input = Self::Input,
230 Size = Self::Size,
231 >
232 where
233 Self: ParUseResult<Elem = &'a O>,
234 O: Copy + 'a,
235 Self::Use: 'a,
236 {
237 let (u, iter, x1, x2, exe, _, params) = self.destruct();
238 ParUseResultIter::new(u, iter, x1, x2.mapped(UFnCopied::new()), exe, params)
239 }
240
241 /// Clones elements of a reference iterator on the success path.
242 ///
243 /// # Examples
244 ///
245 /// ```
246 /// use orx_parallel::*;
247 ///
248 /// let data = vec!["a".to_string(), "b".to_string()];
249 /// let out: Result<Vec<_>, &'static str> = data
250 /// .par()
251 /// .map(Ok::<_, &'static str>)
252 /// .into_fallible()
253 /// .use_new(|_| ())
254 /// .cloned()
255 /// .collect();
256 ///
257 /// assert_eq!(out, Ok(vec!["a".to_string(), "b".to_string()]));
258 /// ```
259 fn cloned<'a, O>(
260 self,
261 ) -> impl ParUseResult<
262 Elem = O,
263 Error = Self::Error,
264 Use = Self::Use,
265 Xap1 = Self::Xap1,
266 M = Self::M,
267 Xap2 = MappedOf<Self::Xap2, UFnCloned<'a, Self::Use, O>>,
268 Input = Self::Input,
269 Size = Self::Size,
270 >
271 where
272 Self: ParUseResult<Elem = &'a O>,
273 O: Clone + 'a,
274 Self::Use: 'a,
275 {
276 let (u, iter, x1, x2, exe, _, params) = self.destruct();
277 ParUseResultIter::new(u, iter, x1, x2.mapped(UFnCloned::new()), exe, params)
278 }
279
280 // transformations
281
282 /// Maps each successful element with closure `h`.
283 ///
284 /// # Examples
285 ///
286 /// ```
287 /// use orx_parallel::*;
288 ///
289 /// let out: Result<Vec<_>, _> = ["1", "2", "3"]
290 /// .into_par()
291 /// .map(|s| s.parse::<usize>())
292 /// .into_fallible()
293 /// .use_new(|_| ())
294 /// .map(|_, x| 2 * x)
295 /// .collect();
296 ///
297 /// assert_eq!(out, Ok(vec![2, 4, 6]));
298 /// ```
299 fn map<Q, H>(
300 self,
301 h: H,
302 ) -> impl ParUseResult<
303 Elem = Q,
304 Error = Self::Error,
305 Use = Self::Use,
306 Xap1 = Self::Xap1,
307 M = Self::M,
308 Xap2 = MapOf<Self::Xap2, Q, H>,
309 Input = Self::Input,
310 Size = Self::Size,
311 >
312 where
313 H: Fn(&mut Self::Use, Self::Elem) -> Q + Copy + Send;
314
315 /// Runs `h` on each successful element and forwards the item unchanged.
316 ///
317 /// # Examples
318 ///
319 /// ```
320 /// use orx_parallel::*;
321 ///
322 /// let mut use_vec = UseVec::new(|_| 0usize);
323 /// let out: Result<Vec<_>, _> = ["1", "2", "3", "4"]
324 /// .into_par()
325 /// .map(|s| s.parse::<usize>())
326 /// .into_fallible()
327 /// .use_vec(&mut use_vec)
328 /// .inspect(|count, _| *count += 1)
329 /// .collect();
330 ///
331 /// assert_eq!(out, Ok(vec![1, 2, 3, 4]));
332 /// assert_eq!(use_vec.into_vec().into_iter().sum::<usize>(), 4);
333 /// ```
334 fn inspect<H>(
335 self,
336 h: H,
337 ) -> impl ParUseResult<
338 Elem = Self::Elem,
339 Error = Self::Error,
340 Use = Self::Use,
341 Xap1 = Self::Xap1,
342 M = Self::M,
343 Xap2 = InsOf<Self::Xap2, H>,
344 Input = Self::Input,
345 Size = Self::Size,
346 >
347 where
348 H: Fn(&mut Self::Use, &Self::Elem) + Copy + Send;
349
350 /// Keeps successful elements satisfying predicate `h`.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// use orx_parallel::*;
356 ///
357 /// let out: Result<Vec<_>, _> = ["1", "2", "3", "4", "5", "6"]
358 /// .into_par()
359 /// .map(|s| s.parse::<usize>())
360 /// .into_fallible()
361 /// .use_new(|_| ())
362 /// .filter(|_, x| x % 2 == 1)
363 /// .collect();
364 ///
365 /// assert_eq!(out, Ok(vec![1, 3, 5]));
366 /// ```
367 fn filter<H>(
368 self,
369 h: H,
370 ) -> impl ParUseResult<
371 Elem = Self::Elem,
372 Error = Self::Error,
373 Use = Self::Use,
374 Xap1 = Self::Xap1,
375 M = Self::M,
376 Xap2 = FilOf<Self::Xap2, H>,
377 Input = Self::Input,
378 Size = <Self::Size as SizePair>::ThenBin,
379 >
380 where
381 H: Fn(&mut Self::Use, &Self::Elem) -> bool + Copy + Send;
382
383 /// Maps and filters successful elements in one pass.
384 ///
385 /// # Examples
386 ///
387 /// ```
388 /// use orx_parallel::*;
389 ///
390 /// let out: Result<Vec<_>, _> = ["1", "x", "5"]
391 /// .into_par()
392 /// .map(Ok::<_, &'static str>)
393 /// .into_fallible()
394 /// .use_new(|_| ())
395 /// .filter_map(|_, s| s.parse::<usize>().ok())
396 /// .collect();
397 ///
398 /// assert_eq!(out, Ok(vec![1, 5]));
399 /// ```
400 fn filter_map<Q, H>(
401 self,
402 h: H,
403 ) -> impl ParUseResult<
404 Elem = Q,
405 Error = Self::Error,
406 Use = Self::Use,
407 Xap1 = Self::Xap1,
408 M = Self::M,
409 Xap2 = FilMapOf<Self::Xap2, Q, H>,
410 Input = Self::Input,
411 Size = <Self::Size as SizePair>::ThenBin,
412 >
413 where
414 H: Fn(&mut Self::Use, Self::Elem) -> Option<Q> + Copy + Send;
415
416 /// Maps each successful element to an iterator and flattens one level.
417 ///
418 /// # Examples
419 ///
420 /// ```
421 /// use orx_parallel::*;
422 ///
423 /// let out: Result<Vec<_>, _> = ["1", "2", "3"]
424 /// .into_par()
425 /// .map(|s| s.parse::<usize>())
426 /// .into_fallible()
427 /// .use_new(|_| ())
428 /// .flat_map(|_, x| [x, x + 10])
429 /// .collect();
430 ///
431 /// assert_eq!(out, Ok(vec![1, 11, 2, 12, 3, 13]));
432 /// ```
433 fn flat_map<V, H>(
434 self,
435 h: H,
436 ) -> impl ParUseResult<
437 Elem = V::Item,
438 Error = Self::Error,
439 Use = Self::Use,
440 Xap1 = Self::Xap1,
441 M = Self::M,
442 Xap2 = FlatMapOf<Self::Xap2, V, H>,
443 Input = Self::Input,
444 Size = <Self::Size as SizePair>::ThenMany,
445 >
446 where
447 V: IntoIterator,
448 H: Fn(&mut Self::Use, Self::Elem) -> V + Copy + Send;
449
450 /// Flattens one level of nested iterables on the success path.
451 ///
452 /// # Examples
453 ///
454 /// ```
455 /// use orx_parallel::*;
456 ///
457 /// let nested = vec![vec![1, 2], vec![3, 4]];
458 /// let out: Result<Vec<_>, &'static str> = nested
459 /// .into_par()
460 /// .map(Ok::<_, &'static str>)
461 /// .into_fallible()
462 /// .use_new(|_| ())
463 /// .flatten()
464 /// .collect();
465 ///
466 /// assert_eq!(out, Ok(vec![1, 2, 3, 4]));
467 /// ```
468 fn flatten(
469 self,
470 ) -> impl ParUseResult<
471 Elem = <Self::Elem as IntoIterator>::Item,
472 Error = Self::Error,
473 Use = Self::Use,
474 Xap1 = Self::Xap1,
475 M = Self::M,
476 Xap2 = FlattenOf<Self::Xap2>,
477 Input = Self::Input,
478 Size = <Self::Size as SizePair>::ThenMany,
479 >
480 where
481 Self::Elem: IntoIterator;
482
483 /// Returns a lower and optional upper bound on the number of successful output items.
484 ///
485 /// The bounds follow the usual [`Iterator::size_hint`] convention.
486 /// The upper bound includes items that may be removed by filtering or short-circuiting.
487 ///
488 /// # Examples
489 ///
490 /// ```
491 /// use orx_parallel::*;
492 ///
493 /// let values = (0..4)
494 /// .into_par()
495 /// .map(Ok::<_, ()>)
496 /// .into_fallible()
497 /// .use_new(|_| ())
498 /// .filter(|_, x| x % 2 == 0);
499 ///
500 /// assert_eq!(values.size_hint(), (0, Some(4)));
501 /// ```
502 fn size_hint(&self) -> (usize, Option<usize>);
503
504 /// Returns the exact number of output items.
505 fn len(&self) -> usize
506 where
507 Self::Input: ExactSizeConcurrentIter,
508 Self: ParUseResult<Size = OneOne>,
509 {
510 self.size_hint().0
511 }
512
513 /// Returns `true` when the parallel iterator has no output items.
514 fn is_empty(&self) -> bool
515 where
516 Self::Input: ExactSizeConcurrentIter,
517 Self: ParUseResult<Size = OneOne>,
518 {
519 self.len() == 0
520 }
521
522 // compute
523
524 /// Returns the first successful item according to iteration order.
525 ///
526 /// Returns:
527 /// - `Err(e)` if computation short-circuits due to a failure
528 /// - `Ok(None)` if no successful element exists
529 /// - `Ok(Some(x))` for the first successful element
530 ///
531 /// # Examples
532 ///
533 /// ```
534 /// use orx_parallel::*;
535 ///
536 /// let ok = ["1", "2", "3"]
537 /// .into_par()
538 /// .map(|s| s.parse::<usize>())
539 /// .into_fallible()
540 /// .use_new(|_| ())
541 /// .first();
542 /// assert_eq!(ok, Ok(Some(1)));
543 ///
544 /// let fail = ["bad", "1", "3"]
545 /// .into_par()
546 /// .map(|s| s.parse::<usize>())
547 /// .into_fallible()
548 /// .use_new(|_| ())
549 /// .first();
550 /// assert!(fail.is_err());
551 /// ```
552 fn first(self) -> Result<Option<Self::Elem>, Self::Error>
553 where
554 Self::Elem: Send,
555 Self::Error: Send;
556
557 /// Reduces successful items into one value using `f`.
558 ///
559 /// Returns `Err(e)` on short-circuit failure.
560 ///
561 /// # Examples
562 ///
563 /// ```
564 /// use orx_parallel::*;
565 ///
566 /// let ok = ["1", "2", "3", "4", "5"]
567 /// .into_par()
568 /// .map(|s| s.parse::<usize>())
569 /// .into_fallible()
570 /// .use_new(|_| ())
571 /// .reduce(|_, a, b| a + b);
572 /// assert_eq!(ok, Ok(Some(15)));
573 ///
574 /// let fail = ["1", "x", "3"]
575 /// .into_par()
576 /// .map(|s| s.parse::<usize>().map_err(|_| "parse"))
577 /// .into_fallible()
578 /// .use_new(|_| ())
579 /// .reduce(|_, a, b| a + b);
580 /// assert_eq!(fail, Err("parse"));
581 /// ```
582 fn reduce<F>(self, f: F) -> Result<Option<Self::Elem>, Self::Error>
583 where
584 F: Fn(&mut Self::Use, Self::Elem, Self::Elem) -> Self::Elem + Send + Copy,
585 Self::Elem: Send,
586 Self::Error: Send;
587
588 /// Collects successful items into `dst`.
589 ///
590 /// Returns `Err(e)` on short-circuit failure.
591 ///
592 /// # Examples
593 ///
594 /// ```
595 /// use orx_parallel::*;
596 ///
597 /// let mut dst = vec![10usize];
598 /// let ok = ["0", "1", "2"]
599 /// .into_par()
600 /// .map(|s| s.parse::<usize>())
601 /// .into_fallible()
602 /// .use_new(|_| ())
603 /// .collect_into(&mut dst);
604 ///
605 /// assert_eq!(ok, Ok(()));
606 /// assert_eq!(dst, vec![10, 0, 1, 2]);
607 /// ```
608 fn collect_into<P>(self, dst: &mut P) -> Result<(), Self::Error>
609 where
610 P: ParExtend<Self::Elem>,
611 Self::Elem: Send,
612 Self::Error: Send;
613
614 /// Collects successful items into a new collection.
615 ///
616 /// Returns `Err(e)` on short-circuit failure.
617 ///
618 /// # Examples
619 ///
620 /// ```
621 /// use orx_parallel::*;
622 ///
623 /// let out: Result<Vec<_>, _> = ["1", "2", "3"]
624 /// .into_par()
625 /// .map(|s| s.parse::<usize>())
626 /// .into_fallible()
627 /// .use_new(|_| ())
628 /// .collect();
629 ///
630 /// assert_eq!(out, Ok(vec![1, 2, 3]));
631 /// ```
632 fn collect<P>(self) -> Result<P, Self::Error>
633 where
634 P: ParExtend<Self::Elem> + Default,
635 Self::Elem: Send,
636 Self::Error: Send,
637 {
638 let mut dst = P::default();
639 self.collect_into(&mut dst)?;
640 Ok(dst)
641 }
642
643 // compute - derived
644
645 /// Returns `Ok(true)` if all successful items satisfy `f`.
646 ///
647 /// Returns `Err(e)` on short-circuit failure.
648 ///
649 /// # Examples
650 ///
651 /// ```
652 /// use orx_parallel::*;
653 ///
654 /// let ok = ["1", "2", "3", "4"]
655 /// .into_par()
656 /// .map(|s| s.parse::<usize>())
657 /// .into_fallible()
658 /// .use_new(|_| ())
659 /// .all(|_, x| x > &0);
660 /// assert_eq!(ok, Ok(true));
661 /// ```
662 fn all<F>(self, f: F) -> Result<bool, Self::Error>
663 where
664 Self::Elem: Send,
665 F: Fn(&mut Self::Use, &Self::Elem) -> bool + Sync,
666 Self::Error: Send,
667 {
668 self.map(|u, x| f(u, &x))
669 .find(|_, x| !*x)
670 .map(|x| x.map(|_| false).unwrap_or(true))
671 }
672
673 /// Returns `Ok(true)` if any successful item satisfies `f`.
674 ///
675 /// Returns `Err(e)` on short-circuit failure.
676 ///
677 /// # Examples
678 ///
679 /// ```
680 /// use orx_parallel::*;
681 ///
682 /// let ok = ["1", "2", "3", "4"]
683 /// .into_par()
684 /// .map(|s| s.parse::<usize>())
685 /// .into_fallible()
686 /// .use_new(|_| ())
687 /// .any(|_, x| x % 2 == 0);
688 /// assert_eq!(ok, Ok(true));
689 /// ```
690 fn any<F>(self, f: F) -> Result<bool, Self::Error>
691 where
692 Self::Elem: Send,
693 F: Fn(&mut Self::Use, &Self::Elem) -> bool + Sync,
694 Self::Error: Send,
695 {
696 self.map(|u, x| f(u, &x))
697 .find(|_, x| *x)
698 .map(|x| x.is_some())
699 }
700
701 /// Counts successful elements.
702 ///
703 /// Returns `Err(e)` on short-circuit failure.
704 ///
705 /// # Examples
706 ///
707 /// ```
708 /// use orx_parallel::*;
709 ///
710 /// let ok = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
711 /// .into_par()
712 /// .map(|s| s.parse::<usize>())
713 /// .into_fallible()
714 /// .use_new(|_| ())
715 /// .filter(|_, x| x % 3 == 0)
716 /// .count();
717 ///
718 /// assert_eq!(ok, Ok(3));
719 /// ```
720 fn count(self) -> Result<usize, Self::Error>
721 where
722 Self::Elem: Send,
723 Self::Error: Send,
724 {
725 self.map(|_, _| 1)
726 .reduce(|_, a, b| a + b)
727 .map(|x| x.unwrap_or(0))
728 }
729
730 /// Finds first (ordered) or any (arbitrary) successful item satisfying `f`.
731 ///
732 /// Returns `Err(e)` on short-circuit failure.
733 ///
734 /// # Examples
735 ///
736 /// ```
737 /// use orx_parallel::*;
738 ///
739 /// let found = (1..101)
740 /// .map(|x| x.to_string())
741 /// .collect::<Vec<_>>()
742 /// .into_par()
743 /// .map(|s| s.parse::<usize>())
744 /// .into_fallible()
745 /// .use_new(|_| ())
746 /// .find(|_, x| x % 17 == 0);
747 ///
748 /// assert_eq!(found, Ok(Some(17)));
749 /// ```
750 fn find<F>(self, f: F) -> Result<Option<Self::Elem>, Self::Error>
751 where
752 Self::Elem: Send,
753 F: Fn(&mut Self::Use, &Self::Elem) -> bool + Sync,
754 Self::Error: Send,
755 {
756 self.filter(&f).first()
757 }
758
759 /// Executes `f` for each successful element.
760 ///
761 /// Returns `Err(e)` on short-circuit failure.
762 ///
763 /// # Examples
764 ///
765 /// ```
766 /// use orx_parallel::*;
767 ///
768 /// let mut sums = UseVec::new(|_| 0usize);
769 /// let result = ["1", "2", "3", "4"]
770 /// .into_par()
771 /// .map(|s| s.parse::<usize>())
772 /// .into_fallible()
773 /// .use_vec(&mut sums)
774 /// .for_each(|local, x| *local += x);
775 ///
776 /// assert_eq!(result, Ok(()));
777 /// assert_eq!(sums.into_vec().into_iter().sum::<usize>(), 10);
778 /// ```
779 fn for_each<F>(self, f: F) -> Result<(), Self::Error>
780 where
781 F: Fn(&mut Self::Use, Self::Elem) + Send + Copy,
782 Self::Error: Send,
783 {
784 self.map(f).reduce(|_, _, _| {}).map(|_| ())
785 }
786
787 /// Returns maximum successful element.
788 ///
789 /// Returns `Err(e)` on short-circuit failure.
790 ///
791 /// # Examples
792 ///
793 /// ```
794 /// use orx_parallel::*;
795 ///
796 /// let m = ["1", "2", "3", "4"]
797 /// .into_par()
798 /// .map(|s| s.parse::<usize>())
799 /// .into_fallible()
800 /// .use_new(|_| ())
801 /// .max();
802 ///
803 /// assert_eq!(m, Ok(Some(4)));
804 /// ```
805 fn max(self) -> Result<Option<Self::Elem>, Self::Error>
806 where
807 Self::Elem: Ord + Send,
808 Self::Error: Send,
809 {
810 self.reduce(|_, a, b| Ord::max(a, b))
811 }
812
813 /// Returns successful element considered maximum by comparator `f`.
814 ///
815 /// Returns `Err(e)` on short-circuit failure.
816 ///
817 /// # Examples
818 ///
819 /// ```
820 /// use orx_parallel::*;
821 ///
822 /// let x = vec![-3_i32, 0, 1, 5, -10]
823 /// .into_par()
824 /// .map(Ok::<_, &'static str>)
825 /// .into_fallible()
826 /// .use_new(|_| ())
827 /// .max_by(|_, a, b| a.cmp(b));
828 ///
829 /// assert_eq!(x, Ok(Some(5)));
830 /// ```
831 fn max_by<F>(self, f: F) -> Result<Option<Self::Elem>, Self::Error>
832 where
833 Self::Elem: Send,
834 F: Fn(&mut Self::Use, &Self::Elem, &Self::Elem) -> Ordering + Sync,
835 Self::Error: Send,
836 {
837 let reduce = |u: &mut Self::Use, x, y| match f(u, &x, &y) {
838 Ordering::Greater | Ordering::Equal => x,
839 Ordering::Less => y,
840 };
841 self.reduce(reduce)
842 }
843
844 /// Returns successful element with maximum key value.
845 ///
846 /// Returns `Err(e)` on short-circuit failure.
847 ///
848 /// # Examples
849 ///
850 /// ```
851 /// use orx_parallel::*;
852 ///
853 /// let x = vec![-3_i32, 0, 1, 5, -10]
854 /// .into_par()
855 /// .map(Ok::<_, &'static str>)
856 /// .into_fallible()
857 /// .use_new(|_| ())
858 /// .max_by_key(|_, x| x.abs());
859 ///
860 /// assert_eq!(x, Ok(Some(-10)));
861 /// ```
862 fn max_by_key<B, F>(self, f: F) -> Result<Option<Self::Elem>, Self::Error>
863 where
864 Self::Elem: Send,
865 B: Ord,
866 F: Fn(&mut Self::Use, &Self::Elem) -> B + Sync,
867 Self::Error: Send,
868 {
869 let reduce = |u: &mut Self::Use, x, y| match f(u, &x).cmp(&f(u, &y)) {
870 Ordering::Greater | Ordering::Equal => x,
871 Ordering::Less => y,
872 };
873 self.reduce(reduce)
874 }
875
876 /// Returns minimum successful element.
877 ///
878 /// Returns `Err(e)` on short-circuit failure.
879 ///
880 /// # Examples
881 ///
882 /// ```
883 /// use orx_parallel::*;
884 ///
885 /// let m = ["1", "2", "3", "4"]
886 /// .into_par()
887 /// .map(|s| s.parse::<usize>())
888 /// .into_fallible()
889 /// .use_new(|_| ())
890 /// .min();
891 ///
892 /// assert_eq!(m, Ok(Some(1)));
893 /// ```
894 fn min(self) -> Result<Option<Self::Elem>, Self::Error>
895 where
896 Self::Elem: Ord + Send,
897 Self::Error: Send,
898 {
899 self.reduce(|_, a, b| Ord::min(a, b))
900 }
901
902 /// Returns successful element considered minimum by comparator `f`.
903 ///
904 /// Returns `Err(e)` on short-circuit failure.
905 ///
906 /// # Examples
907 ///
908 /// ```
909 /// use orx_parallel::*;
910 ///
911 /// let x = vec![-3_i32, 0, 1, 5, -10]
912 /// .into_par()
913 /// .map(Ok::<_, &'static str>)
914 /// .into_fallible()
915 /// .use_new(|_| ())
916 /// .min_by(|_, a, b| a.cmp(b));
917 ///
918 /// assert_eq!(x, Ok(Some(-10)));
919 /// ```
920 fn min_by<F>(self, f: F) -> Result<Option<Self::Elem>, Self::Error>
921 where
922 Self::Elem: Send,
923 F: Fn(&mut Self::Use, &Self::Elem, &Self::Elem) -> Ordering + Sync,
924 Self::Error: Send,
925 {
926 let reduce = |u: &mut Self::Use, x, y| match f(u, &x, &y) {
927 Ordering::Less | Ordering::Equal => x,
928 Ordering::Greater => y,
929 };
930 self.reduce(reduce)
931 }
932
933 /// Returns successful element with minimum key value.
934 ///
935 /// Returns `Err(e)` on short-circuit failure.
936 ///
937 /// # Examples
938 ///
939 /// ```
940 /// use orx_parallel::*;
941 ///
942 /// let x = vec![-3_i32, 0, 1, 5, -10]
943 /// .into_par()
944 /// .map(Ok::<_, &'static str>)
945 /// .into_fallible()
946 /// .use_new(|_| ())
947 /// .min_by_key(|_, x| x.abs());
948 ///
949 /// assert_eq!(x, Ok(Some(0)));
950 /// ```
951 fn min_by_key<B, F>(self, f: F) -> Result<Option<Self::Elem>, Self::Error>
952 where
953 Self::Elem: Send,
954 B: Ord,
955 F: Fn(&mut Self::Use, &Self::Elem) -> B + Sync,
956 Self::Error: Send,
957 {
958 let reduce = |u: &mut Self::Use, x, y| match f(u, &x).cmp(&f(u, &y)) {
959 Ordering::Less | Ordering::Equal => x,
960 Ordering::Greater => y,
961 };
962 self.reduce(reduce)
963 }
964
965 /// Sums successful elements using [`Sum`] implementation.
966 ///
967 /// Returns `Err(e)` on short-circuit failure.
968 ///
969 /// # Examples
970 ///
971 /// ```
972 /// use orx_parallel::*;
973 ///
974 /// let s: Result<usize, _> = ["1", "2", "3", "4"]
975 /// .into_par()
976 /// .map(|s| s.parse::<usize>())
977 /// .into_fallible()
978 /// .use_new(|_| ())
979 /// .sum();
980 ///
981 /// assert_eq!(s, Ok(10));
982 /// ```
983 fn sum<S>(self) -> Result<S, Self::Error>
984 where
985 Self::Elem: Sum<S>,
986 S: Send,
987 Self::Error: Send,
988 {
989 self.map(|_, x| Self::Elem::owned(x))
990 .reduce(|_, a, b| Self::Elem::add(a, b))
991 .map(|x| x.unwrap_or(Self::Elem::zero()))
992 }
993}