1#[fp_macros::document_module]
36mod inner {
37 use {
38 crate::{
39 Apply,
40 brands::TryLazyBrand,
41 classes::{
42 CloneableFn,
43 Deferrable,
44 Foldable,
45 FoldableWithIndex,
46 Monoid,
47 RefFunctor,
48 Semigroup,
49 SendDeferrable,
50 SendRefFunctor,
51 TryLazyConfig,
52 WithIndex,
53 },
54 impl_kind,
55 kinds::*,
56 types::{
57 ArcLazyConfig,
58 Lazy,
59 RcLazyConfig,
60 TrySendThunk,
61 TryThunk,
62 TryTrampoline,
63 },
64 },
65 fp_macros::*,
66 std::{
67 fmt,
68 hash::{
69 Hash,
70 Hasher,
71 },
72 },
73 };
74
75 #[document_type_parameters(
95 "The lifetime of the computation.",
96 "The type of the computed value.",
97 "The type of the error.",
98 "The memoization configuration."
99 )]
100 pub struct TryLazy<'a, A, E, Config: TryLazyConfig = RcLazyConfig>(
106 pub(crate) Config::TryLazy<'a, A, E>,
108 )
109 where
110 A: 'a,
111 E: 'a;
112
113 #[document_type_parameters(
114 "The lifetime of the computation.",
115 "The type of the computed value.",
116 "The type of the error.",
117 "The memoization configuration."
118 )]
119 #[document_parameters("The instance to clone.")]
120 impl<'a, A, E, Config: TryLazyConfig> Clone for TryLazy<'a, A, E, Config>
121 where
122 A: 'a,
123 E: 'a,
124 {
125 #[document_signature]
126 #[document_returns(
127 "A new `TryLazy` instance that shares the same underlying memoized result."
128 )]
129 #[document_examples]
130 fn clone(&self) -> Self {
138 Self(self.0.clone())
139 }
140 }
141
142 #[document_type_parameters(
143 "The lifetime of the computation.",
144 "The type of the computed value.",
145 "The type of the error.",
146 "The memoization configuration."
147 )]
148 #[document_parameters("The `TryLazy` instance.")]
149 impl<'a, A, E, Config: TryLazyConfig> TryLazy<'a, A, E, Config>
150 where
151 A: 'a,
152 E: 'a,
153 {
154 #[document_signature]
164 #[document_returns("A result containing a reference to the value or error.")]
166 #[document_examples]
168 #[inline]
176 pub fn evaluate(&self) -> Result<&A, &E> {
177 Config::try_evaluate(&self.0)
178 }
179 }
180
181 #[document_type_parameters(
182 "The lifetime of the computation.",
183 "The type of the computed value.",
184 "The type of the error."
185 )]
186 #[document_parameters("The try-lazy cell instance.")]
187 impl<'a, A, E> TryLazy<'a, A, E, RcLazyConfig>
188 where
189 A: 'a,
190 E: 'a,
191 {
192 #[document_signature]
194 #[document_parameters("The closure that produces the result.")]
196 #[document_returns("A new `TryLazy` instance.")]
198 #[document_examples]
200 #[inline]
208 pub fn new(f: impl FnOnce() -> Result<A, E> + 'a) -> Self {
209 TryLazy(RcLazyConfig::try_lazy_new(Box::new(f)))
210 }
211
212 #[document_signature]
214 #[document_parameters("The success value to wrap.")]
216 #[document_returns("A new `TryLazy` instance that evaluates to `Ok(&a)`.")]
218 #[document_examples]
220 #[inline]
228 pub fn ok(a: A) -> Self {
229 Self::new(move || Ok(a))
230 }
231
232 #[document_signature]
234 #[document_parameters("The error value to wrap.")]
236 #[document_returns("A new `TryLazy` instance that evaluates to `Err(&e)`.")]
238 #[document_examples]
240 #[inline]
248 pub fn err(e: E) -> Self {
249 Self::new(move || Err(e))
250 }
251
252 #[document_signature]
257 #[document_returns("An owned `Result` clone of the memoized value.")]
259 #[document_examples]
261 #[inline]
270 pub fn evaluate_owned(&self) -> Result<A, E>
271 where
272 A: Clone,
273 E: Clone, {
274 self.evaluate().cloned().map_err(|e| e.clone())
275 }
276
277 #[document_signature]
288 #[document_type_parameters("The type of the mapped success value.")]
290 #[document_parameters("The function to apply to the success value.")]
292 #[document_returns("A new `RcTryLazy` that applies `f` to the success value of this cell.")]
294 #[document_examples]
296 #[inline]
305 pub fn map<B: 'a>(
306 self,
307 f: impl FnOnce(&A) -> B + 'a,
308 ) -> RcTryLazy<'a, B, E>
309 where
310 E: Clone + 'a, {
311 RcTryLazy::new(move || match self.evaluate() {
312 Ok(a) => Ok(f(a)),
313 Err(e) => Err(e.clone()),
314 })
315 }
316
317 #[document_signature]
333 #[document_type_parameters("The type of the mapped success value.")]
334 #[document_parameters("The function to apply to the success value.")]
335 #[document_returns("A new `RcTryLazy` that applies `f` to the success value of this cell.")]
336 #[document_examples]
337 #[inline]
346 pub fn ref_map<B: 'a>(
347 self,
348 f: impl FnOnce(&A) -> B + 'a,
349 ) -> RcTryLazy<'a, B, E>
350 where
351 E: Clone + 'a, {
352 RcTryLazy::new(move || match self.evaluate() {
353 Ok(a) => Ok(f(a)),
354 Err(e) => Err(e.clone()),
355 })
356 }
357
358 #[document_signature]
369 #[document_type_parameters("The type of the mapped error value.")]
371 #[document_parameters("The function to apply to the error value.")]
373 #[document_returns("A new `RcTryLazy` that applies `f` to the error value of this cell.")]
375 #[document_examples]
377 #[inline]
386 pub fn map_err<E2: 'a>(
387 self,
388 f: impl FnOnce(&E) -> E2 + 'a,
389 ) -> RcTryLazy<'a, A, E2>
390 where
391 A: Clone + 'a, {
392 RcTryLazy::new(move || match self.evaluate() {
393 Ok(a) => Ok(a.clone()),
394 Err(e) => Err(f(e)),
395 })
396 }
397
398 #[document_signature]
406 #[document_type_parameters(
408 "The type of the mapped success value.",
409 "The type of the mapped error value."
410 )]
411 #[document_parameters(
413 "The function to apply to the success value.",
414 "The function to apply to the error value."
415 )]
416 #[document_returns(
418 "A new `RcTryLazy` that applies `f` to the success value or `g` to the error value of this cell."
419 )]
420 #[document_examples]
422 #[inline]
435 pub fn bimap<B: 'a, F: 'a>(
436 self,
437 f: impl FnOnce(&A) -> B + 'a,
438 g: impl FnOnce(&E) -> F + 'a,
439 ) -> RcTryLazy<'a, B, F> {
440 RcTryLazy::new(move || match self.evaluate() {
441 Ok(a) => Ok(f(a)),
442 Err(e) => Err(g(e)),
443 })
444 }
445 }
446
447 #[document_type_parameters(
448 "The lifetime of the computation.",
449 "The type of the computed value.",
450 "The type of the error."
451 )]
452 impl<'a, A, E> From<TryThunk<'a, A, E>> for TryLazy<'a, A, E, ArcLazyConfig>
453 where
454 A: Send + Sync + 'a,
455 E: Send + Sync + 'a,
456 {
457 #[document_signature]
462 #[document_parameters("The fallible thunk to convert.")]
463 #[document_returns("A new `TryLazy` instance containing the eagerly evaluated result.")]
464 #[document_examples]
465 fn from(eval: TryThunk<'a, A, E>) -> Self {
473 let result = eval.evaluate();
474 Self::new(move || result)
475 }
476 }
477
478 #[document_type_parameters(
479 "The lifetime of the computation.",
480 "The type of the computed value.",
481 "The type of the error."
482 )]
483 impl<'a, A, E> From<TryTrampoline<A, E>> for TryLazy<'a, A, E, ArcLazyConfig>
484 where
485 A: Send + Sync + 'static,
486 E: Send + Sync + 'static,
487 {
488 #[document_signature]
493 #[document_parameters("The fallible trampoline to convert.")]
494 #[document_returns("A new `TryLazy` instance containing the eagerly evaluated result.")]
495 #[document_examples]
496 fn from(task: TryTrampoline<A, E>) -> Self {
504 let result = task.evaluate();
505 Self::new(move || result)
506 }
507 }
508
509 #[document_type_parameters(
510 "The lifetime of the computation.",
511 "The type of the computed value.",
512 "The type of the error."
513 )]
514 impl<'a, A, E> From<TryThunk<'a, A, E>> for TryLazy<'a, A, E, RcLazyConfig> {
515 #[document_signature]
516 #[document_parameters("The fallible thunk to convert.")]
517 #[document_returns(
518 "A new `TryLazy` instance that will evaluate the thunk on first access."
519 )]
520 #[document_examples]
521 fn from(eval: TryThunk<'a, A, E>) -> Self {
529 Self::new(move || eval.evaluate())
530 }
531 }
532
533 #[document_type_parameters(
534 "The lifetime of the computation.",
535 "The type of the computed value.",
536 "The type of the error."
537 )]
538 impl<'a, A, E> From<TryTrampoline<A, E>> for TryLazy<'a, A, E, RcLazyConfig> {
539 #[document_signature]
540 #[document_parameters("The fallible trampoline to convert.")]
541 #[document_returns(
542 "A new `TryLazy` instance that will evaluate the trampoline on first access."
543 )]
544 #[document_examples]
545 fn from(task: TryTrampoline<A, E>) -> Self {
553 Self::new(move || task.evaluate())
554 }
555 }
556
557 #[document_type_parameters(
558 "The lifetime of the computation.",
559 "The type of the computed value.",
560 "The type of the error."
561 )]
562 impl<'a, A, E> From<Lazy<'a, A, ArcLazyConfig>> for TryLazy<'a, A, E, ArcLazyConfig>
563 where
564 A: Clone + Send + Sync + 'a,
565 E: Send + Sync + 'a,
566 {
567 #[document_signature]
568 #[document_parameters("The thread-safe lazy value to convert.")]
569 #[document_returns("A new `TryLazy` instance that wraps the lazy value.")]
570 #[document_examples]
571 fn from(memo: Lazy<'a, A, ArcLazyConfig>) -> Self {
579 Self::new(move || Ok(memo.evaluate().clone()))
580 }
581 }
582
583 #[document_type_parameters(
584 "The lifetime of the computation.",
585 "The type of the computed value.",
586 "The type of the error."
587 )]
588 impl<'a, A, E> From<Lazy<'a, A, RcLazyConfig>> for TryLazy<'a, A, E, RcLazyConfig>
589 where
590 A: Clone + 'a,
591 E: 'a,
592 {
593 #[document_signature]
594 #[document_parameters("The lazy value to convert.")]
595 #[document_returns("A new `TryLazy` instance that wraps the lazy value.")]
596 #[document_examples]
597 fn from(memo: Lazy<'a, A, RcLazyConfig>) -> Self {
605 Self::new(move || Ok(memo.evaluate().clone()))
606 }
607 }
608
609 #[document_type_parameters(
610 "The lifetime of the computation.",
611 "The type of the computed value.",
612 "The type of the error."
613 )]
614 impl<'a, A: 'a, E: 'a> From<Result<A, E>> for TryLazy<'a, A, E, RcLazyConfig> {
615 #[document_signature]
616 #[document_parameters("The result to convert.")]
617 #[document_returns("A new `TryLazy` instance that produces the result.")]
618 #[document_examples]
619 fn from(result: Result<A, E>) -> Self {
629 Self::new(move || result)
630 }
631 }
632
633 #[document_type_parameters(
634 "The lifetime of the computation.",
635 "The type of the computed value.",
636 "The type of the error."
637 )]
638 impl<'a, A, E> From<Result<A, E>> for TryLazy<'a, A, E, ArcLazyConfig>
639 where
640 A: 'a,
641 E: 'a,
642 Result<A, E>: Send,
643 {
644 #[document_signature]
645 #[document_parameters("The result to convert.")]
646 #[document_returns("A new `TryLazy` instance that produces the result.")]
647 #[document_examples]
648 fn from(result: Result<A, E>) -> Self {
658 Self::new(move || result)
659 }
660 }
661
662 #[document_type_parameters(
663 "The lifetime of the computation.",
664 "The type of the computed value.",
665 "The type of the error."
666 )]
667 impl<'a, A, E> From<TrySendThunk<'a, A, E>> for TryLazy<'a, A, E, ArcLazyConfig>
668 where
669 A: Send + Sync + 'a,
670 E: Send + Sync + 'a,
671 {
672 #[document_signature]
678 #[document_parameters("The fallible send thunk to convert.")]
679 #[document_returns("A thread-safe `ArcTryLazy` that evaluates the thunk on first access.")]
680 #[document_examples]
681 fn from(thunk: TrySendThunk<'a, A, E>) -> Self {
689 thunk.into_arc_try_lazy()
690 }
691 }
692
693 #[document_type_parameters(
694 "The lifetime of the computation.",
695 "The type of the computed value.",
696 "The type of the error."
697 )]
698 impl<'a, A: Clone + Send + Sync + 'a, E: Clone + Send + Sync + 'a>
699 From<TryLazy<'a, A, E, RcLazyConfig>> for TryLazy<'a, A, E, ArcLazyConfig>
700 {
701 #[document_signature]
707 #[document_parameters("The `RcTryLazy` instance to convert.")]
708 #[document_returns(
709 "A new `ArcTryLazy` instance containing a clone of the eagerly evaluated result."
710 )]
711 #[document_examples]
712 fn from(source: TryLazy<'a, A, E, RcLazyConfig>) -> Self {
725 let result: Result<A, E> = source.evaluate().cloned().map_err(Clone::clone);
726 Self::new(move || result)
727 }
728 }
729
730 #[document_type_parameters(
731 "The lifetime of the computation.",
732 "The type of the computed value.",
733 "The type of the error."
734 )]
735 impl<'a, A: Clone + 'a, E: Clone + 'a> From<TryLazy<'a, A, E, ArcLazyConfig>>
736 for TryLazy<'a, A, E, RcLazyConfig>
737 {
738 #[document_signature]
744 #[document_parameters("The `ArcTryLazy` instance to convert.")]
745 #[document_returns(
746 "A new `RcTryLazy` instance containing a clone of the eagerly evaluated result."
747 )]
748 #[document_examples]
749 fn from(source: TryLazy<'a, A, E, ArcLazyConfig>) -> Self {
762 let result: Result<A, E> = source.evaluate().cloned().map_err(Clone::clone);
763 Self::new(move || result)
764 }
765 }
766
767 #[document_type_parameters(
768 "The lifetime of the computation.",
769 "The type of the computed value.",
770 "The type of the error value."
771 )]
772 impl<'a, A: 'a, E: 'a> TryLazy<'a, A, E, RcLazyConfig> {
773 #[document_signature]
780 #[document_parameters(
782 "The closure that might panic.",
783 "The function that converts a panic payload into the error type."
784 )]
785 #[document_returns(
787 "A new `TryLazy` instance where panics are converted to `Err(E)` via the handler."
788 )]
789 #[document_examples]
791 pub fn catch_unwind_with(
807 f: impl FnOnce() -> A + std::panic::UnwindSafe + 'a,
808 handler: impl FnOnce(Box<dyn std::any::Any + Send>) -> E + 'a,
809 ) -> Self {
810 Self::new(move || std::panic::catch_unwind(f).map_err(handler))
811 }
812 }
813
814 #[document_type_parameters(
815 "The lifetime of the computation.",
816 "The type of the computed value."
817 )]
818 impl<'a, A> TryLazy<'a, A, String, RcLazyConfig>
819 where
820 A: 'a,
821 {
822 #[document_signature]
827 #[document_parameters("The closure that might panic.")]
829 #[document_returns("A new `TryLazy` instance where panics are converted to `Err(String)`.")]
831 #[document_examples]
833 pub fn catch_unwind(f: impl FnOnce() -> A + std::panic::UnwindSafe + 'a) -> Self {
846 Self::catch_unwind_with(f, crate::utils::panic_payload_to_string)
847 }
848 }
849
850 #[document_type_parameters(
851 "The lifetime of the computation.",
852 "The type of the computed value.",
853 "The type of the error."
854 )]
855 #[document_parameters("The `TryLazy` instance.")]
856 impl<'a, A, E> TryLazy<'a, A, E, RcLazyConfig>
857 where
858 A: Clone + 'a,
859 E: Clone + 'a,
860 {
861 #[document_signature]
871 #[document_type_parameters("The type of the new success value.")]
873 #[document_parameters("The fallible function to apply to the success value.")]
875 #[document_returns("A new `TryLazy` containing the chained result.")]
877 #[document_examples]
879 pub fn and_then<B: 'a>(
888 self,
889 f: impl FnOnce(&A) -> Result<B, E> + 'a,
890 ) -> TryLazy<'a, B, E, RcLazyConfig> {
891 let fa = self;
892 TryLazy::<'a, B, E, RcLazyConfig>::new(move || match fa.evaluate() {
893 Ok(a) => f(a),
894 Err(e) => Err(e.clone()),
895 })
896 }
897
898 #[document_signature]
904 #[document_parameters("The recovery function to apply to the error value.")]
906 #[document_returns("A new `TryLazy` containing the recovered result.")]
908 #[document_examples]
910 pub fn or_else(
919 self,
920 f: impl FnOnce(&E) -> Result<A, E> + 'a,
921 ) -> TryLazy<'a, A, E, RcLazyConfig> {
922 let fa = self;
923 TryLazy::<'a, A, E, RcLazyConfig>::new(move || match fa.evaluate() {
924 Ok(a) => Ok(a.clone()),
925 Err(e) => f(e),
926 })
927 }
928 }
929
930 #[document_type_parameters(
931 "The lifetime of the computation.",
932 "The type of the computed value.",
933 "The type of the error."
934 )]
935 #[document_parameters("The `TryLazy` instance.")]
936 impl<'a, A, E> TryLazy<'a, A, E, ArcLazyConfig>
937 where
938 A: Clone + Send + Sync + 'a,
939 E: Clone + Send + Sync + 'a,
940 {
941 #[document_signature]
951 #[document_type_parameters("The type of the new success value.")]
953 #[document_parameters("The fallible function to apply to the success value.")]
955 #[document_returns("A new `ArcTryLazy` containing the chained result.")]
957 #[document_examples]
959 pub fn and_then<B: Send + Sync + 'a>(
968 self,
969 f: impl FnOnce(&A) -> Result<B, E> + Send + 'a,
970 ) -> TryLazy<'a, B, E, ArcLazyConfig> {
971 let fa = self;
972 TryLazy::<'a, B, E, ArcLazyConfig>::new(move || match fa.evaluate() {
973 Ok(a) => f(a),
974 Err(e) => Err(e.clone()),
975 })
976 }
977
978 #[document_signature]
984 #[document_parameters("The recovery function to apply to the error value.")]
986 #[document_returns("A new `ArcTryLazy` containing the recovered result.")]
988 #[document_examples]
990 pub fn or_else(
999 self,
1000 f: impl FnOnce(&E) -> Result<A, E> + Send + 'a,
1001 ) -> TryLazy<'a, A, E, ArcLazyConfig> {
1002 let fa = self;
1003 TryLazy::<'a, A, E, ArcLazyConfig>::new(move || match fa.evaluate() {
1004 Ok(a) => Ok(a.clone()),
1005 Err(e) => f(e),
1006 })
1007 }
1008 }
1009
1010 #[document_type_parameters(
1011 "The lifetime of the computation.",
1012 "The type of the computed value.",
1013 "The type of the error."
1014 )]
1015 #[document_parameters("The try-lazy cell instance.")]
1016 impl<'a, A, E> TryLazy<'a, A, E, ArcLazyConfig>
1017 where
1018 A: 'a,
1019 E: 'a,
1020 {
1021 #[document_signature]
1023 #[document_parameters("The closure that produces the result.")]
1025 #[document_returns("A new `TryLazy` instance.")]
1027 #[document_examples]
1029 #[inline]
1037 pub fn new(f: impl FnOnce() -> Result<A, E> + Send + 'a) -> Self {
1038 TryLazy(ArcLazyConfig::try_lazy_new(Box::new(f)))
1039 }
1040
1041 #[document_signature]
1043 #[document_parameters("The success value to wrap.")]
1045 #[document_returns("A new `ArcTryLazy` instance that evaluates to `Ok(&a)`.")]
1047 #[document_examples]
1049 #[inline]
1057 pub fn ok(a: A) -> Self
1058 where
1059 A: Send,
1060 E: Send, {
1061 Self::new(move || Ok(a))
1062 }
1063
1064 #[document_signature]
1066 #[document_parameters("The error value to wrap.")]
1068 #[document_returns("A new `ArcTryLazy` instance that evaluates to `Err(&e)`.")]
1070 #[document_examples]
1072 #[inline]
1080 pub fn err(e: E) -> Self
1081 where
1082 A: Send,
1083 E: Send, {
1084 Self::new(move || Err(e))
1085 }
1086
1087 #[document_signature]
1093 #[document_returns("An owned `Result` clone of the memoized value.")]
1095 #[document_examples]
1097 #[inline]
1106 pub fn evaluate_owned(&self) -> Result<A, E>
1107 where
1108 A: Clone + Send + Sync,
1109 E: Clone + Send + Sync, {
1110 self.evaluate().cloned().map_err(|e| e.clone())
1111 }
1112
1113 #[document_signature]
1119 #[document_type_parameters("The type of the mapped success value.")]
1121 #[document_parameters("The function to apply to the success value.")]
1123 #[document_returns(
1125 "A new `ArcTryLazy` that applies `f` to the success value of this cell."
1126 )]
1127 #[document_examples]
1129 #[inline]
1138 pub fn map<B: 'a>(
1139 self,
1140 f: impl FnOnce(&A) -> B + Send + 'a,
1141 ) -> ArcTryLazy<'a, B, E>
1142 where
1143 A: Send + Sync,
1144 E: Clone + Send + Sync, {
1145 ArcTryLazy::new(move || match self.evaluate() {
1146 Ok(a) => Ok(f(a)),
1147 Err(e) => Err(e.clone()),
1148 })
1149 }
1150
1151 #[document_signature]
1172 #[document_type_parameters("The type of the mapped success value.")]
1173 #[document_parameters("The function to apply to the success value.")]
1174 #[document_returns(
1175 "A new `ArcTryLazy` that applies `f` to the success value of this cell."
1176 )]
1177 #[document_examples]
1178 #[inline]
1187 pub fn ref_map<B: 'a>(
1188 self,
1189 f: impl FnOnce(&A) -> B + Send + 'a,
1190 ) -> ArcTryLazy<'a, B, E>
1191 where
1192 A: Send + Sync,
1193 E: Clone + Send + Sync, {
1194 ArcTryLazy::new(move || match self.evaluate() {
1195 Ok(a) => Ok(f(a)),
1196 Err(e) => Err(e.clone()),
1197 })
1198 }
1199
1200 #[document_signature]
1206 #[document_type_parameters("The type of the mapped error value.")]
1208 #[document_parameters("The function to apply to the error value.")]
1210 #[document_returns("A new `ArcTryLazy` that applies `f` to the error value of this cell.")]
1212 #[document_examples]
1214 #[inline]
1223 pub fn map_err<E2: 'a>(
1224 self,
1225 f: impl FnOnce(&E) -> E2 + Send + 'a,
1226 ) -> ArcTryLazy<'a, A, E2>
1227 where
1228 A: Clone + Send + Sync,
1229 E: Send + Sync, {
1230 ArcTryLazy::new(move || match self.evaluate() {
1231 Ok(a) => Ok(a.clone()),
1232 Err(e) => Err(f(e)),
1233 })
1234 }
1235
1236 #[document_signature]
1245 #[document_type_parameters(
1247 "The type of the mapped success value.",
1248 "The type of the mapped error value."
1249 )]
1250 #[document_parameters(
1252 "The function to apply to the success value.",
1253 "The function to apply to the error value."
1254 )]
1255 #[document_returns(
1257 "A new `ArcTryLazy` that applies `f` to the success value or `g` to the error value of this cell."
1258 )]
1259 #[document_examples]
1261 #[inline]
1274 pub fn bimap<B: 'a, F: 'a>(
1275 self,
1276 f: impl FnOnce(&A) -> B + Send + 'a,
1277 g: impl FnOnce(&E) -> F + Send + 'a,
1278 ) -> ArcTryLazy<'a, B, F>
1279 where
1280 A: Send + Sync,
1281 E: Send + Sync, {
1282 ArcTryLazy::new(move || match self.evaluate() {
1283 Ok(a) => Ok(f(a)),
1284 Err(e) => Err(g(e)),
1285 })
1286 }
1287 }
1288
1289 #[document_type_parameters(
1290 "The lifetime of the computation.",
1291 "The type of the computed value.",
1292 "The type of the error value."
1293 )]
1294 impl<'a, A: 'a, E: 'a> TryLazy<'a, A, E, ArcLazyConfig> {
1295 #[document_signature]
1302 #[document_parameters(
1304 "The closure that might panic.",
1305 "The function that converts a panic payload into the error type."
1306 )]
1307 #[document_returns(
1309 "A new `ArcTryLazy` instance where panics are converted to `Err(E)` via the handler."
1310 )]
1311 #[document_examples]
1313 pub fn catch_unwind_with(
1329 f: impl FnOnce() -> A + std::panic::UnwindSafe + Send + 'a,
1330 handler: impl FnOnce(Box<dyn std::any::Any + Send>) -> E + Send + 'a,
1331 ) -> Self {
1332 Self::new(move || std::panic::catch_unwind(f).map_err(handler))
1333 }
1334 }
1335
1336 #[document_type_parameters(
1337 "The lifetime of the computation.",
1338 "The type of the computed value."
1339 )]
1340 impl<'a, A> TryLazy<'a, A, String, ArcLazyConfig>
1341 where
1342 A: 'a,
1343 {
1344 #[document_signature]
1353 #[document_parameters("The closure that might panic.")]
1355 #[document_returns(
1357 "A new `ArcTryLazy` instance where panics are converted to `Err(String)`."
1358 )]
1359 #[document_examples]
1361 pub fn catch_unwind(f: impl FnOnce() -> A + std::panic::UnwindSafe + Send + 'a) -> Self {
1374 Self::catch_unwind_with(f, crate::utils::panic_payload_to_string)
1375 }
1376 }
1377
1378 #[document_type_parameters(
1379 "The lifetime of the computation.",
1380 "The type of the computed value.",
1381 "The type of the error."
1382 )]
1383 impl<'a, A, E> Deferrable<'a> for TryLazy<'a, A, E, RcLazyConfig>
1384 where
1385 A: Clone + 'a,
1386 E: Clone + 'a,
1387 {
1388 #[document_signature]
1393 #[document_parameters("The thunk that produces the lazy value.")]
1395 #[document_returns("A new `TryLazy` value.")]
1397 #[document_examples]
1399 fn defer(f: impl FnOnce() -> Self + 'a) -> Self
1412 where
1413 Self: Sized, {
1414 Self::new(move || match f().evaluate() {
1415 Ok(a) => Ok(a.clone()),
1416 Err(e) => Err(e.clone()),
1417 })
1418 }
1419 }
1420
1421 impl_kind! {
1422 impl<E: 'static, Config: TryLazyConfig> for TryLazyBrand<E, Config> {
1423 #[document_default]
1424 type Of<'a, A: 'a>: 'a = TryLazy<'a, A, E, Config>;
1425 }
1426 }
1427
1428 #[document_type_parameters(
1429 "The lifetime of the computation.",
1430 "The success value type.",
1431 "The type of the error."
1432 )]
1433 impl<'a, A: Semigroup + Clone + 'a, E: Clone + 'a> Semigroup for TryLazy<'a, A, E, RcLazyConfig> {
1434 #[document_signature]
1439 #[document_parameters("The first `TryLazy`.", "The second `TryLazy`.")]
1441 #[document_returns("A new `RcTryLazy` containing the combined result.")]
1443 #[document_examples]
1445 fn append(
1459 a: Self,
1460 b: Self,
1461 ) -> Self {
1462 RcTryLazy::new(move || {
1463 let a_val = match a.evaluate() {
1464 Ok(v) => v.clone(),
1465 Err(e) => return Err(e.clone()),
1466 };
1467 let b_val = match b.evaluate() {
1468 Ok(v) => v.clone(),
1469 Err(e) => return Err(e.clone()),
1470 };
1471 Ok(Semigroup::append(a_val, b_val))
1472 })
1473 }
1474 }
1475
1476 #[document_type_parameters(
1477 "The lifetime of the computation.",
1478 "The success value type.",
1479 "The type of the error."
1480 )]
1481 impl<'a, A: Semigroup + Clone + Send + Sync + 'a, E: Clone + Send + Sync + 'a> Semigroup
1482 for TryLazy<'a, A, E, ArcLazyConfig>
1483 {
1484 #[document_signature]
1489 #[document_parameters("The first `ArcTryLazy`.", "The second `ArcTryLazy`.")]
1491 #[document_returns("A new `ArcTryLazy` containing the combined result.")]
1493 #[document_examples]
1495 fn append(
1509 a: Self,
1510 b: Self,
1511 ) -> Self {
1512 ArcTryLazy::new(move || {
1513 let a_val = match a.evaluate() {
1514 Ok(v) => v.clone(),
1515 Err(e) => return Err(e.clone()),
1516 };
1517 let b_val = match b.evaluate() {
1518 Ok(v) => v.clone(),
1519 Err(e) => return Err(e.clone()),
1520 };
1521 Ok(Semigroup::append(a_val, b_val))
1522 })
1523 }
1524 }
1525
1526 #[document_type_parameters("The error type.", "The memoization configuration.")]
1527 impl<E: 'static, Config: TryLazyConfig> Foldable for TryLazyBrand<E, Config> {
1528 #[document_signature]
1534 #[document_type_parameters(
1536 "The lifetime of the computation.",
1537 "The brand of the cloneable function to use.",
1538 "The type of the elements in the structure.",
1539 "The type of the accumulator."
1540 )]
1541 #[document_parameters(
1543 "The function to apply to each element and the accumulator.",
1544 "The initial value of the accumulator.",
1545 "The `TryLazy` to fold."
1546 )]
1547 #[document_returns("The final accumulator value.")]
1549 #[document_examples]
1550 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1564 func: impl Fn(A, B) -> B + 'a,
1565 initial: B,
1566 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1567 ) -> B
1568 where
1569 FnBrand: CloneableFn + 'a, {
1570 match fa.evaluate() {
1571 Ok(a) => func(a.clone(), initial),
1572 Err(_) => initial,
1573 }
1574 }
1575
1576 #[document_signature]
1582 #[document_type_parameters(
1584 "The lifetime of the computation.",
1585 "The brand of the cloneable function to use.",
1586 "The type of the elements in the structure.",
1587 "The type of the accumulator."
1588 )]
1589 #[document_parameters(
1591 "The function to apply to the accumulator and each element.",
1592 "The initial value of the accumulator.",
1593 "The `TryLazy` to fold."
1594 )]
1595 #[document_returns("The final accumulator value.")]
1597 #[document_examples]
1598 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1612 func: impl Fn(B, A) -> B + 'a,
1613 initial: B,
1614 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1615 ) -> B
1616 where
1617 FnBrand: CloneableFn + 'a, {
1618 match fa.evaluate() {
1619 Ok(a) => func(initial, a.clone()),
1620 Err(_) => initial,
1621 }
1622 }
1623
1624 #[document_signature]
1629 #[document_type_parameters(
1631 "The lifetime of the computation.",
1632 "The brand of the cloneable function to use.",
1633 "The type of the elements in the structure.",
1634 "The type of the monoid."
1635 )]
1636 #[document_parameters("The mapping function.", "The TryLazy to fold.")]
1638 #[document_returns("The monoid value.")]
1640 #[document_examples]
1641 fn fold_map<'a, FnBrand, A: 'a + Clone, R: Monoid>(
1657 func: impl Fn(A) -> R + 'a,
1658 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1659 ) -> R
1660 where
1661 FnBrand: CloneableFn + 'a, {
1662 match fa.evaluate() {
1663 Ok(a) => func(a.clone()),
1664 Err(_) => Monoid::empty(),
1665 }
1666 }
1667 }
1668
1669 #[document_type_parameters("The error type.", "The memoization configuration.")]
1672 impl<E: 'static, Config: TryLazyConfig> WithIndex for TryLazyBrand<E, Config> {
1673 type Index = ();
1674 }
1675
1676 #[document_type_parameters("The error type.", "The memoization configuration.")]
1679 impl<E: 'static, Config: TryLazyConfig> FoldableWithIndex for TryLazyBrand<E, Config> {
1680 #[document_signature]
1686 #[document_type_parameters(
1688 "The lifetime of the computation.",
1689 "The type of the computed value.",
1690 "The monoid type."
1691 )]
1692 #[document_parameters(
1694 "The function to apply to the index and the value.",
1695 "The `TryLazy` to fold."
1696 )]
1697 #[document_returns("The monoid value.")]
1699 #[document_examples]
1700 fn fold_map_with_index<'a, A: 'a + Clone, R: Monoid>(
1716 f: impl Fn((), A) -> R + 'a,
1717 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1718 ) -> R {
1719 match fa.evaluate() {
1720 Ok(a) => f((), a.clone()),
1721 Err(_) => Monoid::empty(),
1722 }
1723 }
1724 }
1725
1726 #[document_type_parameters(
1727 "The lifetime of the computation.",
1728 "The type of the computed value.",
1729 "The type of the error."
1730 )]
1731 impl<'a, A, E> Deferrable<'a> for TryLazy<'a, A, E, ArcLazyConfig>
1732 where
1733 A: Clone + Send + Sync + 'a,
1734 E: Clone + Send + Sync + 'a,
1735 {
1736 #[document_signature]
1744 #[document_parameters("The thunk that produces the lazy value.")]
1746 #[document_returns("A new `ArcTryLazy` value.")]
1748 #[document_examples]
1750 fn defer(f: impl FnOnce() -> Self + 'a) -> Self
1763 where
1764 Self: Sized, {
1765 f()
1766 }
1767 }
1768
1769 #[document_type_parameters(
1770 "The lifetime of the computation.",
1771 "The type of the computed value.",
1772 "The type of the error."
1773 )]
1774 impl<'a, A, E> SendDeferrable<'a> for TryLazy<'a, A, E, ArcLazyConfig>
1775 where
1776 A: Clone + Send + Sync + 'a,
1777 E: Clone + Send + Sync + 'a,
1778 {
1779 #[document_signature]
1784 #[document_parameters("The thunk that produces the lazy value.")]
1786 #[document_returns("A new `ArcTryLazy` value.")]
1788 #[document_examples]
1790 fn send_defer(f: impl FnOnce() -> Self + Send + 'a) -> Self
1802 where
1803 Self: Sized, {
1804 Self::new(move || match f().evaluate() {
1805 Ok(a) => Ok(a.clone()),
1806 Err(e) => Err(e.clone()),
1807 })
1808 }
1809 }
1810
1811 pub type RcTryLazy<'a, A, E> = TryLazy<'a, A, E, RcLazyConfig>;
1813
1814 pub type ArcTryLazy<'a, A, E> = TryLazy<'a, A, E, ArcLazyConfig>;
1816
1817 #[document_type_parameters("The type of the error.")]
1820 impl<E: 'static + Clone> RefFunctor for TryLazyBrand<E, RcLazyConfig> {
1821 #[document_signature]
1826 #[document_type_parameters(
1828 "The lifetime of the values.",
1829 "The type of the success value.",
1830 "The type of the result."
1831 )]
1832 #[document_parameters(
1834 "The function to apply to the success value.",
1835 "The memoized fallible value."
1836 )]
1837 #[document_returns("A new memoized fallible value containing the mapped result.")]
1839 #[document_examples]
1841 fn ref_map<'a, A: 'a, B: 'a>(
1854 f: impl FnOnce(&A) -> B + 'a,
1855 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1856 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1857 fa.ref_map(f)
1858 }
1859 }
1860
1861 #[document_type_parameters("The type of the error.")]
1864 impl<E: 'static + Clone + Send + Sync> SendRefFunctor for TryLazyBrand<E, ArcLazyConfig> {
1865 #[document_signature]
1870 #[document_type_parameters(
1872 "The lifetime of the values.",
1873 "The type of the success value.",
1874 "The type of the result."
1875 )]
1876 #[document_parameters(
1878 "The function to apply to the success value.",
1879 "The memoized fallible value."
1880 )]
1881 #[document_returns("A new memoized fallible value containing the mapped result.")]
1883 #[document_examples]
1885 fn send_ref_map<'a, A: Send + Sync + 'a, B: Send + Sync + 'a>(
1898 f: impl FnOnce(&A) -> B + Send + 'a,
1899 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1900 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1901 fa.ref_map(f)
1902 }
1903 }
1904
1905 #[document_type_parameters(
1908 "The lifetime of the computation.",
1909 "The type of the computed value.",
1910 "The type of the error."
1911 )]
1912 impl<'a, A: Monoid + Clone + 'a, E: Clone + 'a> Monoid for TryLazy<'a, A, E, RcLazyConfig> {
1913 #[document_signature]
1915 #[document_returns("An `RcTryLazy` producing the identity value wrapped in `Ok`.")]
1917 #[document_examples]
1919 fn empty() -> Self {
1930 RcTryLazy::new(|| Ok(Monoid::empty()))
1931 }
1932 }
1933
1934 #[document_type_parameters(
1935 "The lifetime of the computation.",
1936 "The type of the computed value.",
1937 "The type of the error."
1938 )]
1939 impl<'a, A: Monoid + Clone + Send + Sync + 'a, E: Clone + Send + Sync + 'a> Monoid
1940 for TryLazy<'a, A, E, ArcLazyConfig>
1941 {
1942 #[document_signature]
1944 #[document_returns("An `ArcTryLazy` producing the identity value wrapped in `Ok`.")]
1946 #[document_examples]
1948 fn empty() -> Self {
1959 ArcTryLazy::new(|| Ok(Monoid::empty()))
1960 }
1961 }
1962
1963 #[document_type_parameters(
1966 "The lifetime of the computation.",
1967 "The type of the computed value.",
1968 "The type of the error.",
1969 "The memoization configuration."
1970 )]
1971 #[document_parameters("The try-lazy value to hash.")]
1972 impl<'a, A: Hash + 'a, E: Hash + 'a, Config: TryLazyConfig> Hash for TryLazy<'a, A, E, Config> {
1973 #[document_signature]
1975 #[document_type_parameters("The type of the hasher.")]
1976 #[document_parameters("The hasher state.")]
1978 #[document_examples]
1980 fn hash<H: Hasher>(
2012 &self,
2013 state: &mut H,
2014 ) {
2015 self.evaluate().hash(state)
2016 }
2017 }
2018
2019 #[document_type_parameters(
2022 "The lifetime of the computation.",
2023 "The type of the computed value.",
2024 "The type of the error.",
2025 "The memoization configuration."
2026 )]
2027 #[document_parameters("The try-lazy value to compare.")]
2028 impl<'a, A: PartialEq + 'a, E: PartialEq + 'a, Config: TryLazyConfig> PartialEq
2029 for TryLazy<'a, A, E, Config>
2030 {
2031 #[document_signature]
2035 #[document_parameters("The other try-lazy value to compare with.")]
2036 #[document_returns("`true` if the evaluated results are equal.")]
2037 #[document_examples]
2038 fn eq(
2047 &self,
2048 other: &Self,
2049 ) -> bool {
2050 self.evaluate() == other.evaluate()
2051 }
2052 }
2053
2054 #[document_type_parameters(
2057 "The lifetime of the computation.",
2058 "The type of the computed value.",
2059 "The type of the error.",
2060 "The memoization configuration."
2061 )]
2062 #[document_parameters("The try-lazy value to compare.")]
2063 impl<'a, A: PartialOrd + 'a, E: PartialOrd + 'a, Config: TryLazyConfig> PartialOrd
2064 for TryLazy<'a, A, E, Config>
2065 {
2066 #[document_signature]
2070 #[document_parameters("The other try-lazy value to compare with.")]
2071 #[document_returns(
2072 "The ordering between the evaluated results, or `None` if not comparable."
2073 )]
2074 #[document_examples]
2075 fn partial_cmp(
2084 &self,
2085 other: &Self,
2086 ) -> Option<std::cmp::Ordering> {
2087 self.evaluate().partial_cmp(&other.evaluate())
2088 }
2089 }
2090
2091 #[document_type_parameters(
2094 "The lifetime of the computation.",
2095 "The type of the computed value.",
2096 "The type of the error.",
2097 "The memoization configuration."
2098 )]
2099 impl<'a, A: Eq + 'a, E: Eq + 'a, Config: TryLazyConfig> Eq for TryLazy<'a, A, E, Config> {}
2100
2101 #[document_type_parameters(
2104 "The lifetime of the computation.",
2105 "The type of the computed value.",
2106 "The type of the error.",
2107 "The memoization configuration."
2108 )]
2109 #[document_parameters("The try-lazy value to compare.")]
2110 impl<'a, A: Ord + 'a, E: Ord + 'a, Config: TryLazyConfig> Ord for TryLazy<'a, A, E, Config> {
2111 #[document_signature]
2115 #[document_parameters("The other try-lazy value to compare with.")]
2116 #[document_returns("The ordering between the evaluated results.")]
2117 #[document_examples]
2118 fn cmp(
2127 &self,
2128 other: &Self,
2129 ) -> std::cmp::Ordering {
2130 self.evaluate().cmp(&other.evaluate())
2131 }
2132 }
2133
2134 #[document_type_parameters(
2137 "The lifetime of the computation.",
2138 "The type of the computed value.",
2139 "The type of the error.",
2140 "The memoization configuration."
2141 )]
2142 #[document_parameters("The try-lazy value to display.")]
2143 impl<'a, A: fmt::Display + 'a, E: fmt::Display + 'a, Config: TryLazyConfig> fmt::Display
2144 for TryLazy<'a, A, E, Config>
2145 {
2146 #[document_signature]
2148 #[document_parameters("The formatter.")]
2150 #[document_returns("The formatting result.")]
2152 #[document_examples]
2154 fn fmt(
2171 &self,
2172 f: &mut fmt::Formatter<'_>,
2173 ) -> fmt::Result {
2174 match self.evaluate() {
2175 Ok(a) => write!(f, "Ok({})", a),
2176 Err(e) => write!(f, "Err({})", e),
2177 }
2178 }
2179 }
2180
2181 #[document_type_parameters(
2184 "The lifetime of the computation.",
2185 "The type of the computed value.",
2186 "The type of the error.",
2187 "The memoization configuration."
2188 )]
2189 #[document_parameters("The try-lazy value to format.")]
2190 impl<'a, A, E, Config: TryLazyConfig> fmt::Debug for TryLazy<'a, A, E, Config>
2191 where
2192 A: 'a,
2193 E: 'a,
2194 {
2195 #[document_signature]
2197 #[document_parameters("The formatter.")]
2198 #[document_returns("The formatting result.")]
2199 #[document_examples]
2200 fn fmt(
2207 &self,
2208 f: &mut fmt::Formatter<'_>,
2209 ) -> fmt::Result {
2210 f.write_str("TryLazy(..)")
2211 }
2212 }
2213
2214 #[document_signature]
2228 #[document_type_parameters(
2230 "The lifetime of the computation.",
2231 "The type of the computed value.",
2232 "The type of the error."
2233 )]
2234 #[document_parameters(
2236 "The function that receives a fallible lazy self-reference and produces the result."
2237 )]
2238 #[document_returns("A new `RcTryLazy` instance.")]
2240 #[document_examples]
2242 pub fn rc_try_lazy_fix<'a, A: Clone + 'a, E: Clone + 'a>(
2253 f: impl FnOnce(RcTryLazy<'a, A, E>) -> Result<A, E> + 'a
2254 ) -> RcTryLazy<'a, A, E> {
2255 use std::{
2256 cell::OnceCell,
2257 rc::{
2258 Rc,
2259 Weak,
2260 },
2261 };
2262
2263 #[allow(clippy::type_complexity)]
2264 let cell: Rc<
2265 OnceCell<
2266 Weak<std::cell::LazyCell<Result<A, E>, Box<dyn FnOnce() -> Result<A, E> + 'a>>>,
2267 >,
2268 > = Rc::new(OnceCell::new());
2269 let cell_clone = cell.clone();
2270 let lazy = RcTryLazy::new(move || {
2271 #[allow(clippy::expect_used)]
2275 let weak = cell_clone.get().expect("rc_try_lazy_fix: cell not initialized");
2276 #[allow(clippy::expect_used)]
2277 let self_ref = TryLazy(weak.upgrade().expect("rc_try_lazy_fix: outer lazy was dropped"));
2278 f(self_ref)
2279 });
2280 let _ = cell.set(Rc::downgrade(&lazy.0));
2281 lazy
2282 }
2283
2284 #[document_signature]
2296 #[document_type_parameters(
2298 "The lifetime of the computation.",
2299 "The type of the computed value.",
2300 "The type of the error."
2301 )]
2302 #[document_parameters(
2304 "The function that receives a fallible lazy self-reference and produces the result."
2305 )]
2306 #[document_returns("A new `ArcTryLazy` instance.")]
2308 #[document_examples]
2310 pub fn arc_try_lazy_fix<'a, A: Clone + Send + Sync + 'a, E: Clone + Send + Sync + 'a>(
2321 f: impl FnOnce(ArcTryLazy<'a, A, E>) -> Result<A, E> + Send + 'a
2322 ) -> ArcTryLazy<'a, A, E> {
2323 use std::sync::{
2324 Arc,
2325 OnceLock,
2326 Weak,
2327 };
2328
2329 #[allow(clippy::type_complexity)]
2330 let cell: Arc<
2331 OnceLock<
2332 Weak<
2333 std::sync::LazyLock<
2334 Result<A, E>,
2335 Box<dyn FnOnce() -> Result<A, E> + Send + 'a>,
2336 >,
2337 >,
2338 >,
2339 > = Arc::new(OnceLock::new());
2340 let cell_clone = cell.clone();
2341 let lazy = ArcTryLazy::new(move || {
2342 #[allow(clippy::expect_used)]
2346 let weak = cell_clone.get().expect("arc_try_lazy_fix: cell not initialized");
2347 #[allow(clippy::expect_used)]
2348 let self_ref = TryLazy(weak.upgrade().expect("arc_try_lazy_fix: outer lazy was dropped"));
2349 f(self_ref)
2350 });
2351 let _ = cell.set(Arc::downgrade(&lazy.0));
2352 lazy
2353 }
2354}
2355pub use inner::*;
2356
2357#[cfg(test)]
2358mod tests {
2359 use {
2360 super::*,
2361 crate::{
2362 brands::TryLazyBrand,
2363 types::{
2364 ArcLazyConfig,
2365 RcLazy,
2366 RcLazyConfig,
2367 TrySendThunk,
2368 TryThunk,
2369 TryTrampoline,
2370 },
2371 },
2372 quickcheck_macros::quickcheck,
2373 std::{
2374 cell::RefCell,
2375 rc::Rc,
2376 sync::Arc,
2377 },
2378 };
2379
2380 #[test]
2384 fn test_try_memo_caching_ok() {
2385 let counter = Rc::new(RefCell::new(0));
2386 let counter_clone = counter.clone();
2387 let memo: RcTryLazy<i32, ()> = RcTryLazy::new(move || {
2388 *counter_clone.borrow_mut() += 1;
2389 Ok(42)
2390 });
2391
2392 assert_eq!(*counter.borrow(), 0);
2393 assert_eq!(memo.evaluate(), Ok(&42));
2394 assert_eq!(*counter.borrow(), 1);
2395 assert_eq!(memo.evaluate(), Ok(&42));
2396 assert_eq!(*counter.borrow(), 1);
2397 }
2398
2399 #[test]
2403 fn test_try_memo_caching_err() {
2404 let counter = Rc::new(RefCell::new(0));
2405 let counter_clone = counter.clone();
2406 let memo: RcTryLazy<i32, i32> = RcTryLazy::new(move || {
2407 *counter_clone.borrow_mut() += 1;
2408 Err(0)
2409 });
2410
2411 assert_eq!(*counter.borrow(), 0);
2412 assert_eq!(memo.evaluate(), Err(&0));
2413 assert_eq!(*counter.borrow(), 1);
2414 assert_eq!(memo.evaluate(), Err(&0));
2415 assert_eq!(*counter.borrow(), 1);
2416 }
2417
2418 #[test]
2422 fn test_try_memo_sharing() {
2423 let counter = Rc::new(RefCell::new(0));
2424 let counter_clone = counter.clone();
2425 let memo: RcTryLazy<i32, ()> = RcTryLazy::new(move || {
2426 *counter_clone.borrow_mut() += 1;
2427 Ok(42)
2428 });
2429 let shared = memo.clone();
2430
2431 assert_eq!(memo.evaluate(), Ok(&42));
2432 assert_eq!(*counter.borrow(), 1);
2433 assert_eq!(shared.evaluate(), Ok(&42));
2434 assert_eq!(*counter.borrow(), 1);
2435 }
2436
2437 #[test]
2441 fn test_catch_unwind() {
2442 let memo = RcTryLazy::catch_unwind(|| {
2443 if true {
2444 panic!("oops")
2445 }
2446 42
2447 });
2448
2449 match memo.evaluate() {
2450 Err(e) => assert_eq!(e, "oops"),
2451 Ok(_) => panic!("Should have failed"),
2452 }
2453 }
2454
2455 #[test]
2457 fn test_try_memo_from_try_eval() {
2458 let eval = TryThunk::new(|| Ok::<i32, ()>(42));
2459 let memo = RcTryLazy::from(eval);
2460 assert_eq!(memo.evaluate(), Ok(&42));
2461 }
2462
2463 #[test]
2465 fn test_try_memo_from_try_task() {
2466 let task = TryTrampoline::<i32, ()>::ok(42);
2467 let memo = RcTryLazy::from(task);
2468 assert_eq!(memo.evaluate(), Ok(&42));
2469 }
2470
2471 #[test]
2473 fn test_try_memo_from_rc_memo() {
2474 let memo = RcLazy::new(|| 42);
2475 let try_memo: crate::types::RcTryLazy<i32, ()> = crate::types::RcTryLazy::from(memo);
2476 assert_eq!(try_memo.evaluate(), Ok(&42));
2477 }
2478
2479 #[test]
2481 fn test_try_memo_from_arc_memo() {
2482 use crate::types::ArcLazy;
2483 let memo = ArcLazy::new(|| 42);
2484 let try_memo: crate::types::ArcTryLazy<i32, ()> = crate::types::ArcTryLazy::from(memo);
2485 assert_eq!(try_memo.evaluate(), Ok(&42));
2486 }
2487
2488 #[test]
2490 fn test_send_defer() {
2491 use crate::classes::send_deferrable::send_defer;
2492
2493 let memo: ArcTryLazy<i32, ()> = send_defer(|| ArcTryLazy::new(|| Ok(42)));
2494 assert_eq!(memo.evaluate(), Ok(&42));
2495 }
2496
2497 #[test]
2499 fn test_rc_try_lazy_ok() {
2500 let memo = RcTryLazy::<i32, ()>::ok(42);
2501 assert_eq!(memo.evaluate(), Ok(&42));
2502 }
2503
2504 #[test]
2506 fn test_rc_try_lazy_err() {
2507 let memo = RcTryLazy::<i32, String>::err("error".to_string());
2508 assert_eq!(memo.evaluate(), Err(&"error".to_string()));
2509 }
2510
2511 #[test]
2513 fn test_arc_try_lazy_ok() {
2514 let memo = ArcTryLazy::<i32, ()>::ok(42);
2515 assert_eq!(memo.evaluate(), Ok(&42));
2516 }
2517
2518 #[test]
2520 fn test_arc_try_lazy_err() {
2521 let memo = ArcTryLazy::<i32, String>::err("error".to_string());
2522 assert_eq!(memo.evaluate(), Err(&"error".to_string()));
2523 }
2524
2525 #[test]
2527 fn test_rc_try_lazy_from_result_ok() {
2528 let memo: RcTryLazy<i32, String> = RcTryLazy::from(Ok(42));
2529 assert_eq!(memo.evaluate(), Ok(&42));
2530 }
2531
2532 #[test]
2534 fn test_rc_try_lazy_from_result_err() {
2535 let memo: RcTryLazy<i32, String> = RcTryLazy::from(Err("error".to_string()));
2536 assert_eq!(memo.evaluate(), Err(&"error".to_string()));
2537 }
2538
2539 #[test]
2541 fn test_arc_try_lazy_from_result_ok() {
2542 let memo: ArcTryLazy<i32, String> = ArcTryLazy::from(Ok(42));
2543 assert_eq!(memo.evaluate(), Ok(&42));
2544 }
2545
2546 #[test]
2548 fn test_arc_try_lazy_from_result_err() {
2549 let memo: ArcTryLazy<i32, String> = ArcTryLazy::from(Err("error".to_string()));
2550 assert_eq!(memo.evaluate(), Err(&"error".to_string()));
2551 }
2552
2553 #[test]
2560 fn test_panic_poisoning() {
2561 use std::panic;
2562
2563 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| {
2564 panic!("initializer panic");
2565 });
2566
2567 let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
2568 let _ = memo.evaluate();
2569 }));
2570 assert!(result.is_err(), "First evaluate should panic");
2571
2572 let result2 = panic::catch_unwind(panic::AssertUnwindSafe(|| {
2573 let _ = memo.evaluate();
2574 }));
2575 assert!(result2.is_err(), "Second evaluate should also panic (poisoned)");
2576 }
2577
2578 #[test]
2585 fn test_arc_try_lazy_thread_safety() {
2586 use std::{
2587 sync::atomic::{
2588 AtomicUsize,
2589 Ordering,
2590 },
2591 thread,
2592 };
2593
2594 let counter = Arc::new(AtomicUsize::new(0));
2595 let counter_clone = counter.clone();
2596 let memo: ArcTryLazy<i32, String> = ArcTryLazy::new(move || {
2597 counter_clone.fetch_add(1, Ordering::SeqCst);
2598 Ok(42)
2599 });
2600
2601 let mut handles = vec![];
2602 for _ in 0 .. 10 {
2603 let memo_clone = memo.clone();
2604 handles.push(thread::spawn(move || {
2605 assert_eq!(memo_clone.evaluate(), Ok(&42));
2606 }));
2607 }
2608
2609 for handle in handles {
2610 handle.join().unwrap();
2611 }
2612
2613 assert_eq!(counter.load(Ordering::SeqCst), 1);
2614 }
2615
2616 #[quickcheck]
2620 fn memoization_ok(x: i32) -> bool {
2621 let memo: RcTryLazy<i32, i32> = RcTryLazy::new(move || Ok(x));
2622 let first = memo.evaluate();
2623 let second = memo.evaluate();
2624 first == second && first == Ok(&x)
2625 }
2626
2627 #[quickcheck]
2629 fn memoization_err(e: i32) -> bool {
2630 let memo: RcTryLazy<i32, i32> = RcTryLazy::new(move || Err(e));
2631 let first = memo.evaluate();
2632 let second = memo.evaluate();
2633 first == second && first == Err(&e)
2634 }
2635
2636 #[quickcheck]
2638 fn deferrable_transparency(x: i32) -> bool {
2639 use crate::classes::send_deferrable::send_defer;
2640
2641 let memo: ArcTryLazy<i32, i32> = ArcTryLazy::new(move || Ok(x));
2642 let deferred: ArcTryLazy<i32, i32> = send_defer(move || ArcTryLazy::new(move || Ok(x)));
2643 memo.evaluate() == deferred.evaluate()
2644 }
2645
2646 #[test]
2650 fn test_arc_catch_unwind() {
2651 let memo = ArcTryLazy::catch_unwind(|| {
2652 if true {
2653 panic!("oops")
2654 }
2655 42
2656 });
2657
2658 match memo.evaluate() {
2659 Err(e) => assert_eq!(e, "oops"),
2660 Ok(_) => panic!("Should have failed"),
2661 }
2662 }
2663
2664 #[test]
2668 fn test_arc_catch_unwind_success() {
2669 let memo = ArcTryLazy::catch_unwind(|| 42);
2670 assert_eq!(memo.evaluate(), Ok(&42));
2671 }
2672
2673 #[test]
2677 fn test_rc_catch_unwind_with_panic() {
2678 let memo = RcTryLazy::<i32, i32>::catch_unwind_with(
2679 || {
2680 if true {
2681 panic!("oops")
2682 }
2683 42
2684 },
2685 |_payload| -1,
2686 );
2687 assert_eq!(memo.evaluate(), Err(&-1));
2688 }
2689
2690 #[test]
2694 fn test_rc_catch_unwind_with_success() {
2695 let memo = RcTryLazy::<i32, i32>::catch_unwind_with(|| 42, |_payload| -1);
2696 assert_eq!(memo.evaluate(), Ok(&42));
2697 }
2698
2699 #[test]
2703 fn test_arc_catch_unwind_with_panic() {
2704 let memo = ArcTryLazy::<i32, i32>::catch_unwind_with(
2705 || {
2706 if true {
2707 panic!("oops")
2708 }
2709 42
2710 },
2711 |_payload| -1,
2712 );
2713 assert_eq!(memo.evaluate(), Err(&-1));
2714 }
2715
2716 #[test]
2720 fn test_arc_catch_unwind_with_success() {
2721 let memo = ArcTryLazy::<i32, i32>::catch_unwind_with(|| 42, |_payload| -1);
2722 assert_eq!(memo.evaluate(), Ok(&42));
2723 }
2724
2725 #[test]
2729 fn test_rc_try_lazy_map_ok() {
2730 let memo = RcTryLazy::<i32, String>::ok(10);
2731 let mapped = memo.map(|a| a * 2);
2732 assert_eq!(mapped.evaluate(), Ok(&20));
2733 }
2734
2735 #[test]
2739 fn test_rc_try_lazy_map_err() {
2740 let memo = RcTryLazy::<i32, String>::err("error".to_string());
2741 let mapped = memo.map(|a| a * 2);
2742 assert_eq!(mapped.evaluate(), Err(&"error".to_string()));
2743 }
2744
2745 #[test]
2749 fn test_rc_try_lazy_map_err_err() {
2750 let memo = RcTryLazy::<i32, String>::err("error".to_string());
2751 let mapped = memo.map_err(|e| format!("wrapped: {}", e));
2752 assert_eq!(mapped.evaluate(), Err(&"wrapped: error".to_string()));
2753 }
2754
2755 #[test]
2759 fn test_rc_try_lazy_map_err_ok() {
2760 let memo = RcTryLazy::<i32, String>::ok(42);
2761 let mapped = memo.map_err(|e| format!("wrapped: {}", e));
2762 assert_eq!(mapped.evaluate(), Ok(&42));
2763 }
2764
2765 #[test]
2769 fn test_rc_try_lazy_bimap_ok() {
2770 let memo = RcTryLazy::<i32, String>::ok(10);
2771 let mapped = memo.bimap(|a| a * 2, |e| e.len());
2772 assert_eq!(mapped.evaluate(), Ok(&20));
2773 }
2774
2775 #[test]
2779 fn test_rc_try_lazy_bimap_err() {
2780 let memo = RcTryLazy::<i32, String>::err("error".to_string());
2781 let mapped = memo.bimap(|a| a * 2, |e| e.len());
2782 assert_eq!(mapped.evaluate(), Err(&5));
2783 }
2784
2785 #[test]
2789 fn test_arc_try_lazy_map_ok() {
2790 let memo = ArcTryLazy::<i32, String>::ok(10);
2791 let mapped = memo.map(|a| a * 2);
2792 assert_eq!(mapped.evaluate(), Ok(&20));
2793 }
2794
2795 #[test]
2799 fn test_arc_try_lazy_map_err() {
2800 let memo = ArcTryLazy::<i32, String>::err("error".to_string());
2801 let mapped = memo.map(|a| a * 2);
2802 assert_eq!(mapped.evaluate(), Err(&"error".to_string()));
2803 }
2804
2805 #[test]
2809 fn test_arc_try_lazy_map_err_err() {
2810 let memo = ArcTryLazy::<i32, String>::err("error".to_string());
2811 let mapped = memo.map_err(|e| format!("wrapped: {}", e));
2812 assert_eq!(mapped.evaluate(), Err(&"wrapped: error".to_string()));
2813 }
2814
2815 #[test]
2819 fn test_arc_try_lazy_map_err_ok() {
2820 let memo = ArcTryLazy::<i32, String>::ok(42);
2821 let mapped = memo.map_err(|e| format!("wrapped: {}", e));
2822 assert_eq!(mapped.evaluate(), Ok(&42));
2823 }
2824
2825 #[test]
2829 fn test_arc_try_lazy_bimap_ok() {
2830 let memo = ArcTryLazy::<i32, String>::ok(10);
2831 let mapped = memo.bimap(|a| a * 2, |e| e.len());
2832 assert_eq!(mapped.evaluate(), Ok(&20));
2833 }
2834
2835 #[test]
2839 fn test_arc_try_lazy_bimap_err() {
2840 let memo = ArcTryLazy::<i32, String>::err("error".to_string());
2841 let mapped = memo.bimap(|a| a * 2, |e| e.len());
2842 assert_eq!(mapped.evaluate(), Err(&5));
2843 }
2844
2845 #[test]
2849 fn test_ref_functor_rc_try_lazy_ok() {
2850 use crate::{
2851 brands::TryLazyBrand,
2852 classes::RefFunctor,
2853 };
2854 let memo = RcTryLazy::<i32, String>::ok(10);
2855 let mapped = TryLazyBrand::<String, RcLazyConfig>::ref_map(|x: &i32| *x * 3, memo);
2856 assert_eq!(mapped.evaluate(), Ok(&30));
2857 }
2858
2859 #[test]
2861 fn test_ref_functor_rc_try_lazy_err() {
2862 use crate::{
2863 brands::TryLazyBrand,
2864 classes::RefFunctor,
2865 };
2866 let memo = RcTryLazy::<i32, String>::err("fail".to_string());
2867 let mapped = TryLazyBrand::<String, RcLazyConfig>::ref_map(|x: &i32| *x * 3, memo);
2868 assert_eq!(mapped.evaluate(), Err(&"fail".to_string()));
2869 }
2870
2871 #[test]
2873 fn test_ref_functor_rc_try_lazy_identity() {
2874 use crate::{
2875 brands::TryLazyBrand,
2876 classes::RefFunctor,
2877 };
2878 let memo = RcTryLazy::<i32, String>::ok(42);
2879 let mapped = TryLazyBrand::<String, RcLazyConfig>::ref_map(|x: &i32| *x, memo.clone());
2880 assert_eq!(mapped.evaluate(), Ok(&42));
2881 }
2882
2883 #[test]
2887 fn test_send_ref_functor_arc_try_lazy_ok() {
2888 use crate::{
2889 brands::TryLazyBrand,
2890 classes::SendRefFunctor,
2891 };
2892 let memo = ArcTryLazy::<i32, String>::ok(10);
2893 let mapped = TryLazyBrand::<String, ArcLazyConfig>::send_ref_map(|x: &i32| *x * 3, memo);
2894 assert_eq!(mapped.evaluate(), Ok(&30));
2895 }
2896
2897 #[test]
2899 fn test_send_ref_functor_arc_try_lazy_err() {
2900 use crate::{
2901 brands::TryLazyBrand,
2902 classes::SendRefFunctor,
2903 };
2904 let memo = ArcTryLazy::<i32, String>::err("fail".to_string());
2905 let mapped = TryLazyBrand::<String, ArcLazyConfig>::send_ref_map(|x: &i32| *x * 3, memo);
2906 assert_eq!(mapped.evaluate(), Err(&"fail".to_string()));
2907 }
2908
2909 #[test]
2913 fn test_rc_try_lazy_ref_map_ok() {
2914 let memo = RcTryLazy::<i32, String>::ok(10);
2915 let mapped = memo.ref_map(|x| *x * 2);
2916 assert_eq!(mapped.evaluate(), Ok(&20));
2917 }
2918
2919 #[test]
2921 fn test_rc_try_lazy_ref_map_err() {
2922 let memo = RcTryLazy::<i32, String>::err("fail".to_string());
2923 let mapped = memo.ref_map(|x| *x * 2);
2924 assert_eq!(mapped.evaluate(), Err(&"fail".to_string()));
2925 }
2926
2927 #[test]
2929 fn test_rc_try_lazy_ref_map_identity() {
2930 let memo = RcTryLazy::<i32, String>::ok(42);
2931 let mapped = memo.ref_map(|x| *x);
2932 assert_eq!(mapped.evaluate(), Ok(&42));
2933 }
2934
2935 #[test]
2937 fn test_arc_try_lazy_ref_map_ok() {
2938 let memo = ArcTryLazy::<i32, String>::ok(10);
2939 let mapped = memo.ref_map(|x| *x * 2);
2940 assert_eq!(mapped.evaluate(), Ok(&20));
2941 }
2942
2943 #[test]
2945 fn test_arc_try_lazy_ref_map_err() {
2946 let memo = ArcTryLazy::<i32, String>::err("fail".to_string());
2947 let mapped = memo.ref_map(|x| *x * 2);
2948 assert_eq!(mapped.evaluate(), Err(&"fail".to_string()));
2949 }
2950
2951 #[test]
2953 fn test_arc_try_lazy_ref_map_identity() {
2954 let memo = ArcTryLazy::<i32, String>::ok(42);
2955 let mapped = memo.ref_map(|x| *x);
2956 assert_eq!(mapped.evaluate(), Ok(&42));
2957 }
2958
2959 #[test]
2963 fn test_semigroup_rc_try_lazy_both_ok() {
2964 use crate::functions::append;
2965 let a = RcTryLazy::<String, String>::ok("Hello".to_string());
2966 let b = RcTryLazy::<String, String>::ok(" World".to_string());
2967 let c = append(a, b);
2968 assert_eq!(c.evaluate(), Ok(&"Hello World".to_string()));
2969 }
2970
2971 #[test]
2973 fn test_semigroup_rc_try_lazy_first_err() {
2974 use crate::functions::append;
2975 let a = RcTryLazy::<String, String>::err("err1".to_string());
2976 let b = RcTryLazy::<String, String>::ok("ok".to_string());
2977 let c = append(a, b);
2978 assert_eq!(c.evaluate(), Err(&"err1".to_string()));
2979 }
2980
2981 #[test]
2983 fn test_semigroup_rc_try_lazy_second_err() {
2984 use crate::functions::append;
2985 let a = RcTryLazy::<String, String>::ok("ok".to_string());
2986 let b = RcTryLazy::<String, String>::err("err2".to_string());
2987 let c = append(a, b);
2988 assert_eq!(c.evaluate(), Err(&"err2".to_string()));
2989 }
2990
2991 #[test]
2993 fn test_semigroup_arc_try_lazy_both_ok() {
2994 use crate::functions::append;
2995 let a = ArcTryLazy::<String, String>::ok("Hello".to_string());
2996 let b = ArcTryLazy::<String, String>::ok(" World".to_string());
2997 let c = append(a, b);
2998 assert_eq!(c.evaluate(), Ok(&"Hello World".to_string()));
2999 }
3000
3001 #[test]
3003 fn test_semigroup_arc_try_lazy_first_err() {
3004 use crate::functions::append;
3005 let a = ArcTryLazy::<String, String>::err("err1".to_string());
3006 let b = ArcTryLazy::<String, String>::ok("ok".to_string());
3007 let c = append(a, b);
3008 assert_eq!(c.evaluate(), Err(&"err1".to_string()));
3009 }
3010
3011 #[test]
3015 fn test_monoid_rc_try_lazy_empty() {
3016 use crate::functions::empty;
3017 let t: RcTryLazy<String, ()> = empty();
3018 assert_eq!(t.evaluate(), Ok(&String::new()));
3019 }
3020
3021 #[test]
3023 fn test_monoid_arc_try_lazy_empty() {
3024 use crate::functions::empty;
3025 let t: ArcTryLazy<String, ()> = empty();
3026 assert_eq!(t.evaluate(), Ok(&String::new()));
3027 }
3028
3029 #[test]
3031 fn test_monoid_rc_try_lazy_left_identity() {
3032 use crate::functions::{
3033 append,
3034 empty,
3035 };
3036 let a = RcTryLazy::<String, ()>::ok("hello".to_string());
3037 let result = append(empty::<RcTryLazy<String, ()>>(), a);
3038 assert_eq!(result.evaluate(), Ok(&"hello".to_string()));
3039 }
3040
3041 #[test]
3043 fn test_monoid_rc_try_lazy_right_identity() {
3044 use crate::functions::{
3045 append,
3046 empty,
3047 };
3048 let a = RcTryLazy::<String, ()>::ok("hello".to_string());
3049 let result = append(a, empty::<RcTryLazy<String, ()>>());
3050 assert_eq!(result.evaluate(), Ok(&"hello".to_string()));
3051 }
3052
3053 #[test]
3057 fn test_foldable_rc_try_lazy_fold_right_ok() {
3058 use crate::functions::fold_right;
3059 let lazy = RcTryLazy::<i32, String>::ok(10);
3060 let result = fold_right::<crate::brands::RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3061 |a, b| a + b,
3062 5,
3063 lazy,
3064 );
3065 assert_eq!(result, 15);
3066 }
3067
3068 #[test]
3070 fn test_foldable_rc_try_lazy_fold_right_err() {
3071 use crate::functions::fold_right;
3072 let lazy = RcTryLazy::<i32, String>::err("fail".to_string());
3073 let result = fold_right::<crate::brands::RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3074 |a, b| a + b,
3075 5,
3076 lazy,
3077 );
3078 assert_eq!(result, 5);
3079 }
3080
3081 #[test]
3083 fn test_foldable_rc_try_lazy_fold_left_ok() {
3084 use crate::functions::fold_left;
3085 let lazy = RcTryLazy::<i32, String>::ok(10);
3086 let result = fold_left::<crate::brands::RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3087 |b, a| b + a,
3088 5,
3089 lazy,
3090 );
3091 assert_eq!(result, 15);
3092 }
3093
3094 #[test]
3096 fn test_foldable_rc_try_lazy_fold_left_err() {
3097 use crate::functions::fold_left;
3098 let lazy = RcTryLazy::<i32, String>::err("fail".to_string());
3099 let result = fold_left::<crate::brands::RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3100 |b, a| b + a,
3101 5,
3102 lazy,
3103 );
3104 assert_eq!(result, 5);
3105 }
3106
3107 #[test]
3109 fn test_foldable_rc_try_lazy_fold_map_ok() {
3110 use crate::functions::fold_map;
3111 let lazy = RcTryLazy::<i32, String>::ok(10);
3112 let result = fold_map::<crate::brands::RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3113 |a: i32| a.to_string(),
3114 lazy,
3115 );
3116 assert_eq!(result, "10");
3117 }
3118
3119 #[test]
3121 fn test_foldable_rc_try_lazy_fold_map_err() {
3122 use crate::functions::fold_map;
3123 let lazy = RcTryLazy::<i32, String>::err("fail".to_string());
3124 let result = fold_map::<crate::brands::RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3125 |a: i32| a.to_string(),
3126 lazy,
3127 );
3128 assert_eq!(result, "");
3129 }
3130
3131 #[test]
3133 fn test_foldable_arc_try_lazy_fold_right_ok() {
3134 use crate::functions::fold_right;
3135 let lazy = ArcTryLazy::<i32, String>::ok(10);
3136 let result = fold_right::<
3137 crate::brands::ArcFnBrand,
3138 TryLazyBrand<String, ArcLazyConfig>,
3139 _,
3140 _,
3141 >(|a, b| a + b, 5, lazy);
3142 assert_eq!(result, 15);
3143 }
3144
3145 #[test]
3147 fn test_foldable_arc_try_lazy_fold_right_err() {
3148 use crate::functions::fold_right;
3149 let lazy = ArcTryLazy::<i32, String>::err("fail".to_string());
3150 let result = fold_right::<
3151 crate::brands::ArcFnBrand,
3152 TryLazyBrand<String, ArcLazyConfig>,
3153 _,
3154 _,
3155 >(|a, b| a + b, 5, lazy);
3156 assert_eq!(result, 5);
3157 }
3158
3159 #[test]
3165 fn test_rc_try_lazy_fold_map_with_index_ok() {
3166 use crate::classes::foldable_with_index::FoldableWithIndex;
3167
3168 let lazy = RcTryLazy::<i32, ()>::ok(42);
3169 let result = <TryLazyBrand<(), RcLazyConfig> as FoldableWithIndex>::fold_map_with_index(
3170 |_, x: i32| x.to_string(),
3171 lazy,
3172 );
3173 assert_eq!(result, "42");
3174 }
3175
3176 #[test]
3180 fn test_rc_try_lazy_fold_map_with_index_err() {
3181 use crate::classes::foldable_with_index::FoldableWithIndex;
3182
3183 let lazy = RcTryLazy::<i32, String>::err("fail".to_string());
3184 let result = <TryLazyBrand<String, RcLazyConfig> as FoldableWithIndex>::fold_map_with_index(
3185 |_, x: i32| x.to_string(),
3186 lazy,
3187 );
3188 assert_eq!(result, "");
3189 }
3190
3191 #[test]
3195 fn test_arc_try_lazy_fold_map_with_index_ok() {
3196 use crate::classes::foldable_with_index::FoldableWithIndex;
3197
3198 let lazy = ArcTryLazy::<i32, ()>::ok(10);
3199 let result = <TryLazyBrand<(), ArcLazyConfig> as FoldableWithIndex>::fold_map_with_index(
3200 |_, x: i32| x.to_string(),
3201 lazy,
3202 );
3203 assert_eq!(result, "10");
3204 }
3205
3206 #[test]
3210 fn test_arc_try_lazy_fold_map_with_index_err() {
3211 use crate::classes::foldable_with_index::FoldableWithIndex;
3212
3213 let lazy = ArcTryLazy::<i32, String>::err("fail".to_string());
3214 let result =
3215 <TryLazyBrand<String, ArcLazyConfig> as FoldableWithIndex>::fold_map_with_index(
3216 |_, x: i32| x.to_string(),
3217 lazy,
3218 );
3219 assert_eq!(result, "");
3220 }
3221
3222 #[test]
3226 fn test_rc_try_lazy_foldable_with_index_compatibility() {
3227 use crate::{
3228 classes::foldable_with_index::FoldableWithIndex,
3229 functions::*,
3230 };
3231
3232 let lazy1 = RcTryLazy::<i32, ()>::ok(7);
3233 let lazy2 = RcTryLazy::<i32, ()>::ok(7);
3234 let f = |a: i32| a.to_string();
3235
3236 let fold_result =
3237 fold_map::<crate::brands::RcFnBrand, TryLazyBrand<(), RcLazyConfig>, _, String>(
3238 f, lazy1,
3239 );
3240 let fold_with_index_result =
3241 <TryLazyBrand<(), RcLazyConfig> as FoldableWithIndex>::fold_map_with_index(
3242 |_, a| f(a),
3243 lazy2,
3244 );
3245 assert_eq!(fold_result, fold_with_index_result);
3246 }
3247
3248 #[test]
3252 fn test_semigroup_append_first_err_short_circuits() {
3253 use {
3254 crate::classes::Semigroup,
3255 std::cell::Cell,
3256 };
3257
3258 let counter = Rc::new(Cell::new(0u32));
3259 let counter_clone = counter.clone();
3260
3261 let a: RcTryLazy<String, String> = RcTryLazy::new(|| Err("first failed".into()));
3262 let b: RcTryLazy<String, String> = RcTryLazy::new(move || {
3263 counter_clone.set(counter_clone.get() + 1);
3264 Ok("second".into())
3265 });
3266
3267 let result = Semigroup::append(a, b);
3268 assert_eq!(result.evaluate(), Err(&"first failed".to_string()));
3269 assert_eq!(counter.get(), 0, "second operand should not be evaluated");
3270 }
3271
3272 #[test]
3276 fn test_semigroup_append_second_err() {
3277 use crate::classes::Semigroup;
3278
3279 let a: RcTryLazy<String, String> = RcTryLazy::new(|| Ok("hello".into()));
3280 let b: RcTryLazy<String, String> = RcTryLazy::new(|| Err("second failed".into()));
3281
3282 let result = Semigroup::append(a, b);
3283 assert_eq!(result.evaluate(), Err(&"second failed".to_string()));
3284 }
3285
3286 #[test]
3288 fn test_semigroup_append_both_ok() {
3289 use crate::classes::Semigroup;
3290
3291 let a: RcTryLazy<String, ()> = RcTryLazy::new(|| Ok("Hello".into()));
3292 let b: RcTryLazy<String, ()> = RcTryLazy::new(|| Ok(" World".into()));
3293
3294 let result = Semigroup::append(a, b);
3295 assert_eq!(result.evaluate(), Ok(&"Hello World".to_string()));
3296 }
3297
3298 #[test]
3300 fn test_map_ok() {
3301 let memo = RcTryLazy::new(|| Ok::<i32, ()>(21));
3302 let mapped = memo.map(|x| x * 2);
3303 assert_eq!(mapped.evaluate(), Ok(&42));
3304 }
3305
3306 #[test]
3308 fn test_map_err() {
3309 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| Err("oops".into()));
3310 let mapped = memo.map(|x| x * 2);
3311 assert_eq!(mapped.evaluate(), Err(&"oops".to_string()));
3312 }
3313
3314 #[test]
3316 fn test_map_err_on_err() {
3317 let memo: RcTryLazy<i32, i32> = RcTryLazy::new(|| Err(21));
3318 let mapped = memo.map_err(|e| e * 2);
3319 assert_eq!(mapped.evaluate(), Err(&42));
3320 }
3321
3322 #[test]
3324 fn test_map_err_on_ok() {
3325 let memo: RcTryLazy<i32, i32> = RcTryLazy::new(|| Ok(42));
3326 let mapped = memo.map_err(|e| e * 2);
3327 assert_eq!(mapped.evaluate(), Ok(&42));
3328 }
3329
3330 #[test]
3332 fn test_and_then_ok() {
3333 let memo = RcTryLazy::new(|| Ok::<i32, String>(21));
3334 let chained = memo.and_then(|x| Ok(x * 2));
3335 assert_eq!(chained.evaluate(), Ok(&42));
3336 }
3337
3338 #[test]
3340 fn test_and_then_chained_err() {
3341 let memo = RcTryLazy::new(|| Ok::<i32, String>(21));
3342 let chained = memo.and_then(|_: &i32| Err::<i32, String>("chained failure".into()));
3343 assert_eq!(chained.evaluate(), Err(&"chained failure".to_string()));
3344 }
3345
3346 #[test]
3348 fn test_and_then_initial_err() {
3349 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| Err("initial".into()));
3350 let chained = memo.and_then(|x| Ok(x * 2));
3351 assert_eq!(chained.evaluate(), Err(&"initial".to_string()));
3352 }
3353
3354 #[test]
3356 fn test_or_else_recovers() {
3357 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| Err("oops".into()));
3358 let recovered = memo.or_else(|_| Ok(42));
3359 assert_eq!(recovered.evaluate(), Ok(&42));
3360 }
3361
3362 #[test]
3364 fn test_or_else_noop_on_ok() {
3365 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| Ok(42));
3366 let recovered = memo.or_else(|_| Ok(99));
3367 assert_eq!(recovered.evaluate(), Ok(&42));
3368 }
3369
3370 #[test]
3372 fn test_or_else_recovery_fails() {
3373 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| Err("first".into()));
3374 let recovered = memo.or_else(|_| Err("second".into()));
3375 assert_eq!(recovered.evaluate(), Err(&"second".to_string()));
3376 }
3377
3378 #[test]
3380 fn test_foldable_ok() {
3381 use crate::{
3382 brands::*,
3383 functions::*,
3384 };
3385
3386 let memo: RcTryLazy<i32, ()> = RcTryLazy::new(|| Ok(10));
3387 let result =
3388 fold_right::<RcFnBrand, TryLazyBrand<(), RcLazyConfig>, _, _>(|a, b| a + b, 5, memo);
3389 assert_eq!(result, 15);
3390 }
3391
3392 #[test]
3394 fn test_foldable_err() {
3395 use crate::{
3396 brands::*,
3397 functions::*,
3398 };
3399
3400 let memo: RcTryLazy<i32, String> = RcTryLazy::new(|| Err("oops".into()));
3401 let result = fold_right::<RcFnBrand, TryLazyBrand<String, RcLazyConfig>, _, _>(
3402 |a, b| a + b,
3403 5,
3404 memo,
3405 );
3406 assert_eq!(result, 5);
3407 }
3408
3409 #[test]
3411 fn test_from_try_send_thunk_ok() {
3412 let counter = Arc::new(std::sync::atomic::AtomicUsize::new(0));
3413 let counter_clone = counter.clone();
3414 let thunk: TrySendThunk<i32, ()> = TrySendThunk::new(move || {
3415 counter_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
3416 Ok(42)
3417 });
3418
3419 assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 0);
3421
3422 let lazy: ArcTryLazy<i32, ()> = ArcTryLazy::from(thunk);
3423 assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 0);
3424
3425 assert_eq!(lazy.evaluate(), Ok(&42));
3427 assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3428
3429 assert_eq!(lazy.evaluate(), Ok(&42));
3431 assert_eq!(counter.load(std::sync::atomic::Ordering::SeqCst), 1);
3432 }
3433
3434 #[test]
3436 fn test_from_try_send_thunk_err() {
3437 let thunk: TrySendThunk<i32, String> = TrySendThunk::new(move || Err("fail".to_string()));
3438 let lazy: ArcTryLazy<i32, String> = ArcTryLazy::from(thunk);
3439 assert_eq!(lazy.evaluate(), Err(&"fail".to_string()));
3440 }
3441
3442 #[test]
3444 fn test_try_send_thunk_into_arc_try_lazy() {
3445 let thunk: TrySendThunk<i32, ()> = TrySendThunk::ok(42);
3446 let lazy: ArcTryLazy<i32, ()> = thunk.into();
3447 assert_eq!(lazy.evaluate(), Ok(&42));
3448 }
3449
3450 #[test]
3454 fn test_try_lazy_partial_eq_ok() {
3455 let a = RcTryLazy::<i32, ()>::ok(42);
3456 let b = RcTryLazy::<i32, ()>::ok(42);
3457 assert_eq!(a, b);
3458 }
3459
3460 #[test]
3462 fn test_try_lazy_partial_eq_ok_neq() {
3463 let a = RcTryLazy::<i32, ()>::ok(1);
3464 let b = RcTryLazy::<i32, ()>::ok(2);
3465 assert_ne!(a, b);
3466 }
3467
3468 #[test]
3470 fn test_try_lazy_partial_eq_err() {
3471 let a = RcTryLazy::<i32, String>::err("fail".to_string());
3472 let b = RcTryLazy::<i32, String>::err("fail".to_string());
3473 assert_eq!(a, b);
3474 }
3475
3476 #[test]
3478 fn test_try_lazy_partial_eq_ok_vs_err() {
3479 let a = RcTryLazy::<i32, i32>::ok(1);
3480 let b = RcTryLazy::<i32, i32>::err(1);
3481 assert_ne!(a, b);
3482 }
3483
3484 #[test]
3486 fn test_try_lazy_partial_eq_arc() {
3487 let a = ArcTryLazy::<i32, ()>::ok(42);
3488 let b = ArcTryLazy::<i32, ()>::ok(42);
3489 assert_eq!(a, b);
3490 }
3491
3492 #[test]
3496 fn test_try_lazy_hash_eq() {
3497 use std::{
3498 collections::hash_map::DefaultHasher,
3499 hash::{
3500 Hash,
3501 Hasher,
3502 },
3503 };
3504
3505 let a = RcTryLazy::<i32, ()>::ok(42);
3506 let b = RcTryLazy::<i32, ()>::ok(42);
3507
3508 let mut h1 = DefaultHasher::new();
3509 a.hash(&mut h1);
3510 let mut h2 = DefaultHasher::new();
3511 b.hash(&mut h2);
3512
3513 assert_eq!(h1.finish(), h2.finish());
3514 }
3515
3516 #[test]
3518 fn test_try_lazy_hash_matches_result() {
3519 use std::{
3520 collections::hash_map::DefaultHasher,
3521 hash::{
3522 Hash,
3523 Hasher,
3524 },
3525 };
3526
3527 let lazy = RcTryLazy::<i32, ()>::ok(42);
3528 let mut h1 = DefaultHasher::new();
3529 lazy.hash(&mut h1);
3530
3531 let result: Result<&i32, &()> = Ok(&42);
3532 let mut h2 = DefaultHasher::new();
3533 result.hash(&mut h2);
3534
3535 assert_eq!(h1.finish(), h2.finish());
3536 }
3537
3538 #[test]
3542 fn test_try_lazy_partial_ord_ok() {
3543 let a = RcTryLazy::<i32, ()>::ok(1);
3544 let b = RcTryLazy::<i32, ()>::ok(2);
3545 assert!(a < b);
3546 assert!(b > a);
3547 }
3548
3549 #[test]
3551 fn test_try_lazy_partial_ord_eq() {
3552 let a = RcTryLazy::<i32, ()>::ok(42);
3553 let b = RcTryLazy::<i32, ()>::ok(42);
3554 assert!(a <= b);
3555 assert!(a >= b);
3556 }
3557
3558 #[test]
3562 fn test_try_lazy_ord_ok() {
3563 use std::cmp::Ordering;
3564
3565 let a = RcTryLazy::<i32, ()>::ok(1);
3566 let b = RcTryLazy::<i32, ()>::ok(2);
3567 assert_eq!(a.cmp(&b), Ordering::Less);
3568 assert_eq!(b.cmp(&a), Ordering::Greater);
3569 }
3570
3571 #[test]
3573 fn test_try_lazy_ord_eq() {
3574 use std::cmp::Ordering;
3575
3576 let a = RcTryLazy::<i32, ()>::ok(42);
3577 let b = RcTryLazy::<i32, ()>::ok(42);
3578 assert_eq!(a.cmp(&b), Ordering::Equal);
3579 }
3580
3581 #[test]
3583 fn test_try_lazy_ord_arc() {
3584 use std::cmp::Ordering;
3585
3586 let a = ArcTryLazy::<i32, ()>::ok(1);
3587 let b = ArcTryLazy::<i32, ()>::ok(2);
3588 assert_eq!(a.cmp(&b), Ordering::Less);
3589 }
3590
3591 #[test]
3593 fn test_try_lazy_eq_trait() {
3594 fn assert_eq_impl<T: Eq>(_: &T) {}
3595 let a = RcTryLazy::<i32, ()>::ok(42);
3596 assert_eq_impl(&a);
3597 }
3598
3599 #[test]
3603 fn test_try_lazy_display_ok_rc() {
3604 let lazy = RcTryLazy::<i32, String>::ok(42);
3605 assert_eq!(format!("{}", lazy), "Ok(42)");
3606 }
3607
3608 #[test]
3610 fn test_try_lazy_display_err_rc() {
3611 let lazy = RcTryLazy::<i32, String>::err("oops".to_string());
3612 assert_eq!(format!("{}", lazy), "Err(oops)");
3613 }
3614
3615 #[test]
3617 fn test_try_lazy_display_ok_arc() {
3618 let lazy = ArcTryLazy::<i32, String>::ok(42);
3619 assert_eq!(format!("{}", lazy), "Ok(42)");
3620 }
3621
3622 #[test]
3624 fn test_try_lazy_display_err_arc() {
3625 let lazy = ArcTryLazy::<i32, String>::err("oops".to_string());
3626 assert_eq!(format!("{}", lazy), "Err(oops)");
3627 }
3628
3629 #[test]
3633 fn test_try_lazy_rc_to_arc_ok() {
3634 let rc_lazy = RcTryLazy::<i32, String>::ok(42);
3635 let arc_lazy: ArcTryLazy<i32, String> = ArcTryLazy::from(rc_lazy);
3636 assert_eq!(arc_lazy.evaluate(), Ok(&42));
3637 }
3638
3639 #[test]
3641 fn test_try_lazy_rc_to_arc_err() {
3642 let rc_lazy = RcTryLazy::<i32, String>::err("fail".to_string());
3643 let arc_lazy: ArcTryLazy<i32, String> = ArcTryLazy::from(rc_lazy);
3644 assert_eq!(arc_lazy.evaluate(), Err(&"fail".to_string()));
3645 }
3646
3647 #[test]
3649 fn test_try_lazy_arc_to_rc_ok() {
3650 let arc_lazy = ArcTryLazy::<i32, String>::ok(42);
3651 let rc_lazy: RcTryLazy<i32, String> = RcTryLazy::from(arc_lazy);
3652 assert_eq!(rc_lazy.evaluate(), Ok(&42));
3653 }
3654
3655 #[test]
3657 fn test_try_lazy_arc_to_rc_err() {
3658 let arc_lazy = ArcTryLazy::<i32, String>::err("fail".to_string());
3659 let rc_lazy: RcTryLazy<i32, String> = RcTryLazy::from(arc_lazy);
3660 assert_eq!(rc_lazy.evaluate(), Err(&"fail".to_string()));
3661 }
3662
3663 #[test]
3668 fn test_rc_try_lazy_fix_ok_constant() {
3669 let fixed = rc_try_lazy_fix(|_self_ref: RcTryLazy<i32, ()>| Ok(42));
3670 assert_eq!(fixed.evaluate(), Ok(&42));
3671 }
3672
3673 #[test]
3676 fn test_rc_try_lazy_fix_err_constant() {
3677 let fixed = rc_try_lazy_fix(|_self_ref: RcTryLazy<i32, String>| Err("fail".to_string()));
3678 assert_eq!(fixed.evaluate(), Err(&"fail".to_string()));
3679 }
3680
3681 #[test]
3683 fn test_rc_try_lazy_fix_memoization() {
3684 let counter = Rc::new(RefCell::new(0));
3685 let counter_clone = counter.clone();
3686 let fixed = rc_try_lazy_fix(move |_self_ref: RcTryLazy<i32, ()>| {
3687 *counter_clone.borrow_mut() += 1;
3688 Ok(100)
3689 });
3690
3691 assert_eq!(*counter.borrow(), 0);
3692 assert_eq!(fixed.evaluate(), Ok(&100));
3693 assert_eq!(*counter.borrow(), 1);
3694 assert_eq!(fixed.evaluate(), Ok(&100));
3696 assert_eq!(*counter.borrow(), 1);
3697 }
3698
3699 #[test]
3701 fn test_rc_try_lazy_fix_self_reference() {
3702 let fixed = rc_try_lazy_fix(|self_ref: RcTryLazy<Vec<i32>, ()>| {
3703 let _ = self_ref;
3705 Ok(vec![1, 2, 3])
3706 });
3707 assert_eq!(fixed.evaluate(), Ok(&vec![1, 2, 3]));
3708 }
3709
3710 #[test]
3712 fn test_rc_try_lazy_fix_clone_sharing() {
3713 let fixed = rc_try_lazy_fix(|_self_ref: RcTryLazy<i32, ()>| Ok(55));
3714 let cloned = fixed.clone();
3715 assert_eq!(fixed.evaluate(), Ok(&55));
3716 assert_eq!(cloned.evaluate(), Ok(&55));
3717 }
3718
3719 #[test]
3721 fn test_rc_try_lazy_fix_uses_self_ref() {
3722 let counter = Rc::new(RefCell::new(0));
3723 let counter_clone = counter.clone();
3724 let lazy = rc_try_lazy_fix(move |self_ref: RcTryLazy<i32, ()>| {
3725 *counter_clone.borrow_mut() += 1;
3726 let _ = self_ref;
3727 Ok(42)
3728 });
3729 assert_eq!(lazy.evaluate(), Ok(&42));
3730 assert_eq!(*counter.borrow(), 1);
3731 assert_eq!(lazy.evaluate(), Ok(&42));
3733 assert_eq!(*counter.borrow(), 1);
3734 }
3735
3736 #[test]
3739 fn test_arc_try_lazy_fix_ok_constant() {
3740 let fixed = arc_try_lazy_fix(|_self_ref: ArcTryLazy<i32, ()>| Ok(42));
3741 assert_eq!(fixed.evaluate(), Ok(&42));
3742 }
3743
3744 #[test]
3747 fn test_arc_try_lazy_fix_err_constant() {
3748 let fixed = arc_try_lazy_fix(|_self_ref: ArcTryLazy<i32, String>| Err("fail".to_string()));
3749 assert_eq!(fixed.evaluate(), Err(&"fail".to_string()));
3750 }
3751
3752 #[test]
3754 fn test_arc_try_lazy_fix_memoization() {
3755 use std::sync::atomic::{
3756 AtomicUsize,
3757 Ordering,
3758 };
3759
3760 let counter = Arc::new(AtomicUsize::new(0));
3761 let counter_clone = counter.clone();
3762 let fixed = arc_try_lazy_fix(move |_self_ref: ArcTryLazy<i32, ()>| {
3763 counter_clone.fetch_add(1, Ordering::SeqCst);
3764 Ok(100)
3765 });
3766
3767 assert_eq!(counter.load(Ordering::SeqCst), 0);
3768 assert_eq!(fixed.evaluate(), Ok(&100));
3769 assert_eq!(counter.load(Ordering::SeqCst), 1);
3770 assert_eq!(fixed.evaluate(), Ok(&100));
3772 assert_eq!(counter.load(Ordering::SeqCst), 1);
3773 }
3774
3775 #[test]
3777 fn test_arc_try_lazy_fix_self_reference() {
3778 let fixed = arc_try_lazy_fix(|self_ref: ArcTryLazy<Vec<i32>, ()>| {
3779 let _ = self_ref;
3780 Ok(vec![1, 2, 3])
3781 });
3782 assert_eq!(fixed.evaluate(), Ok(&vec![1, 2, 3]));
3783 }
3784
3785 #[test]
3787 fn test_arc_try_lazy_fix_uses_self_ref() {
3788 use std::sync::atomic::{
3789 AtomicUsize,
3790 Ordering,
3791 };
3792
3793 let counter = Arc::new(AtomicUsize::new(0));
3794 let counter_clone = counter.clone();
3795 let lazy = arc_try_lazy_fix(move |self_ref: ArcTryLazy<i32, ()>| {
3796 counter_clone.fetch_add(1, Ordering::SeqCst);
3797 let _ = self_ref;
3798 Ok(42)
3799 });
3800 assert_eq!(lazy.evaluate(), Ok(&42));
3801 assert_eq!(counter.load(Ordering::SeqCst), 1);
3802 assert_eq!(lazy.evaluate(), Ok(&42));
3804 assert_eq!(counter.load(Ordering::SeqCst), 1);
3805 }
3806
3807 #[test]
3809 fn test_arc_try_lazy_fix_thread_safety() {
3810 use std::thread;
3811
3812 let lazy = arc_try_lazy_fix(|self_ref: ArcTryLazy<i32, ()>| {
3813 let _ = self_ref;
3814 Ok(42)
3815 });
3816
3817 let mut handles = vec![];
3818 for _ in 0 .. 10 {
3819 let lazy_clone = lazy.clone();
3820 handles.push(thread::spawn(move || {
3821 assert_eq!(lazy_clone.evaluate(), Ok(&42));
3822 }));
3823 }
3824
3825 for handle in handles {
3826 handle.join().unwrap();
3827 }
3828 }
3829}