Skip to main content

fp_library/types/
lazy.rs

1use crate::{
2	Apply,
3	brands::LazyBrand,
4	classes::{CloneableFn, Defer, RefFunctor, SendDefer},
5	impl_kind,
6	kinds::*,
7	types::{Thunk, Trampoline},
8};
9use std::{
10	cell::LazyCell,
11	rc::Rc,
12	sync::{Arc, LazyLock},
13};
14
15/// Configuration for memoization strategy.
16///
17/// This trait bundles together the choices for:
18/// - Pointer type ([`Rc`] vs [`Arc`]).
19/// - Lazy cell type ([`LazyCell`] vs [`LazyLock`]).
20///
21/// # Note on Standard Library Usage
22///
23/// This design leverages Rust 1.80's `LazyCell` and `LazyLock` types,
24/// which encapsulate the initialization-once logic.
25pub trait LazyConfig: 'static {
26	/// The lazy cell type for infallible memoization.
27	type Lazy<'a, A: 'a>: Clone;
28
29	/// The lazy cell type for fallible memoization.
30	type TryLazy<'a, A: 'a, E: 'a>: Clone;
31
32	/// The type of the initializer thunk.
33	type Init<'a, A: 'a>: ?Sized;
34
35	/// The type of the fallible initializer thunk.
36	type TryInit<'a, A: 'a, E: 'a>: ?Sized;
37
38	/// Creates a new lazy cell from an initializer.
39	///
40	/// ### Type Signature
41	///
42	/// `forall a. (Unit -> a) -> Lazy a`
43	///
44	/// ### Type Parameters
45	///
46	/// * `A`: The type of the value.
47	///
48	/// ### Parameters
49	///
50	/// * `f`: The initializer thunk.
51	///
52	/// ### Returns
53	///
54	/// A new lazy cell.
55	///
56	/// ### Examples
57	///
58	/// ```
59	/// use fp_library::types::*;
60	///
61	/// let lazy = RcLazyConfig::new_lazy(Box::new(|| 42));
62	/// assert_eq!(*RcLazyConfig::force(&lazy), 42);
63	/// ```
64	fn new_lazy<'a, A: 'a>(f: Box<Self::Init<'a, A>>) -> Self::Lazy<'a, A>;
65
66	/// Creates a new fallible lazy cell from an initializer.
67	///
68	/// ### Type Signature
69	///
70	/// `forall e a. (Unit -> Result a e) -> TryLazy a e`
71	///
72	/// ### Type Parameters
73	///
74	/// * `A`: The type of the value.
75	/// * `E`: The type of the error.
76	///
77	/// ### Parameters
78	///
79	/// * `f`: The initializer thunk.
80	///
81	/// ### Returns
82	///
83	/// A new fallible lazy cell.
84	///
85	/// ### Examples
86	///
87	/// ```
88	/// use fp_library::types::*;
89	///
90	/// let lazy = RcLazyConfig::new_try_lazy(Box::new(|| Ok::<i32, ()>(42)));
91	/// assert_eq!(RcLazyConfig::force_try(&lazy), Ok(&42));
92	/// ```
93	fn new_try_lazy<'a, A: 'a, E: 'a>(f: Box<Self::TryInit<'a, A, E>>) -> Self::TryLazy<'a, A, E>;
94
95	/// Forces evaluation and returns a reference.
96	///
97	/// ### Type Signature
98	///
99	/// `forall a. Lazy a -> a`
100	///
101	/// ### Type Parameters
102	///
103	/// * `A`: The type of the value.
104	///
105	/// ### Parameters
106	///
107	/// * `lazy`: The lazy cell to force.
108	///
109	/// ### Returns
110	///
111	/// A reference to the value.
112	///
113	/// ### Examples
114	///
115	/// ```
116	/// use fp_library::types::*;
117	///
118	/// let lazy = RcLazyConfig::new_lazy(Box::new(|| 42));
119	/// assert_eq!(*RcLazyConfig::force(&lazy), 42);
120	/// ```
121	fn force<'a, 'b, A: 'a>(lazy: &'b Self::Lazy<'a, A>) -> &'b A;
122
123	/// Forces evaluation and returns a reference to the result.
124	///
125	/// ### Type Signature
126	///
127	/// `forall e a. TryLazy a e -> Result a e`
128	///
129	/// ### Type Parameters
130	///
131	/// * `A`: The type of the value.
132	/// * `E`: The type of the error.
133	///
134	/// ### Parameters
135	///
136	/// * `lazy`: The fallible lazy cell to force.
137	///
138	/// ### Returns
139	///
140	/// A result containing a reference to the value or error.
141	///
142	/// ### Examples
143	///
144	/// ```
145	/// use fp_library::types::*;
146	///
147	/// let lazy = RcLazyConfig::new_try_lazy(Box::new(|| Ok::<i32, ()>(42)));
148	/// assert_eq!(RcLazyConfig::force_try(&lazy), Ok(&42));
149	/// ```
150	fn force_try<'a, 'b, A: 'a, E: 'a>(lazy: &'b Self::TryLazy<'a, A, E>) -> Result<&'b A, &'b E>;
151}
152
153/// Single-threaded memoization using `Rc<LazyCell>`.
154///
155/// Not thread-safe. Use [`ArcLazyConfig`] for multi-threaded contexts.
156pub struct RcLazyConfig;
157
158impl LazyConfig for RcLazyConfig {
159	type Lazy<'a, A: 'a> = Rc<LazyCell<A, Box<dyn FnOnce() -> A + 'a>>>;
160	type TryLazy<'a, A: 'a, E: 'a> =
161		Rc<LazyCell<Result<A, E>, Box<dyn FnOnce() -> Result<A, E> + 'a>>>;
162	type Init<'a, A: 'a> = dyn FnOnce() -> A + 'a;
163	type TryInit<'a, A: 'a, E: 'a> = dyn FnOnce() -> Result<A, E> + 'a;
164
165	/// Creates a new lazy cell from an initializer.
166	///
167	/// ### Type Signature
168	///
169	/// `forall a. (Unit -> a) -> Lazy a`
170	///
171	/// ### Type Parameters
172	///
173	/// * `A`: The type of the value.
174	///
175	/// ### Parameters
176	///
177	/// * `f`: The initializer thunk.
178	///
179	/// ### Returns
180	///
181	/// A new lazy cell.
182	///
183	/// ### Examples
184	///
185	/// ```
186	/// use fp_library::types::*;
187	///
188	/// let lazy = RcLazyConfig::new_lazy(Box::new(|| 42));
189	/// assert_eq!(*RcLazyConfig::force(&lazy), 42);
190	/// ```
191	fn new_lazy<'a, A: 'a>(f: Box<Self::Init<'a, A>>) -> Self::Lazy<'a, A> {
192		Rc::new(LazyCell::new(f))
193	}
194
195	/// Creates a new fallible lazy cell from an initializer.
196	///
197	/// ### Type Signature
198	///
199	/// `forall e a. (Unit -> Result a e) -> TryLazy a e`
200	///
201	/// ### Type Parameters
202	///
203	/// * `A`: The type of the value.
204	/// * `E`: The type of the error.
205	///
206	/// ### Parameters
207	///
208	/// * `f`: The initializer thunk.
209	///
210	/// ### Returns
211	///
212	/// A new fallible lazy cell.
213	///
214	/// ### Examples
215	///
216	/// ```
217	/// use fp_library::types::*;
218	///
219	/// let lazy = RcLazyConfig::new_try_lazy(Box::new(|| Ok::<i32, ()>(42)));
220	/// assert_eq!(RcLazyConfig::force_try(&lazy), Ok(&42));
221	/// ```
222	fn new_try_lazy<'a, A: 'a, E: 'a>(f: Box<Self::TryInit<'a, A, E>>) -> Self::TryLazy<'a, A, E> {
223		Rc::new(LazyCell::new(f))
224	}
225
226	/// Forces evaluation and returns a reference.
227	///
228	/// ### Type Signature
229	///
230	/// `forall a. Lazy a -> a`
231	///
232	/// ### Type Parameters
233	///
234	/// * `A`: The type of the value.
235	///
236	/// ### Parameters
237	///
238	/// * `lazy`: The lazy cell to force.
239	///
240	/// ### Returns
241	///
242	/// A reference to the value.
243	///
244	/// ### Examples
245	///
246	/// ```
247	/// use fp_library::types::*;
248	///
249	/// let lazy = RcLazyConfig::new_lazy(Box::new(|| 42));
250	/// assert_eq!(*RcLazyConfig::force(&lazy), 42);
251	/// ```
252	fn force<'a, 'b, A: 'a>(lazy: &'b Self::Lazy<'a, A>) -> &'b A {
253		LazyCell::force(lazy)
254	}
255
256	/// Forces evaluation and returns a reference to the result.
257	///
258	/// ### Type Signature
259	///
260	/// `forall e a. TryLazy a e -> Result a e`
261	///
262	/// ### Type Parameters
263	///
264	/// * `A`: The type of the value.
265	/// * `E`: The type of the error.
266	///
267	/// ### Parameters
268	///
269	/// * `lazy`: The fallible lazy cell to force.
270	///
271	/// ### Returns
272	///
273	/// A result containing a reference to the value or error.
274	///
275	/// ### Examples
276	///
277	/// ```
278	/// use fp_library::types::*;
279	///
280	/// let lazy = RcLazyConfig::new_try_lazy(Box::new(|| Ok::<i32, ()>(42)));
281	/// assert_eq!(RcLazyConfig::force_try(&lazy), Ok(&42));
282	/// ```
283	fn force_try<'a, 'b, A: 'a, E: 'a>(lazy: &'b Self::TryLazy<'a, A, E>) -> Result<&'b A, &'b E> {
284		LazyCell::force(lazy).as_ref()
285	}
286}
287
288/// Thread-safe memoization using `Arc<LazyLock>`.
289///
290/// Requires `A: Send + Sync` for the value type.
291pub struct ArcLazyConfig;
292
293impl LazyConfig for ArcLazyConfig {
294	type Lazy<'a, A: 'a> = Arc<LazyLock<A, Box<dyn FnOnce() -> A + Send + 'a>>>;
295	type TryLazy<'a, A: 'a, E: 'a> =
296		Arc<LazyLock<Result<A, E>, Box<dyn FnOnce() -> Result<A, E> + Send + 'a>>>;
297	type Init<'a, A: 'a> = dyn FnOnce() -> A + Send + 'a;
298	type TryInit<'a, A: 'a, E: 'a> = dyn FnOnce() -> Result<A, E> + Send + 'a;
299
300	/// Creates a new lazy cell from an initializer.
301	///
302	/// ### Type Signature
303	///
304	/// `forall a. (Unit -> a) -> Lazy a`
305	///
306	/// ### Type Parameters
307	///
308	/// * `A`: The type of the value.
309	///
310	/// ### Parameters
311	///
312	/// * `f`: The initializer thunk.
313	///
314	/// ### Returns
315	///
316	/// A new lazy cell.
317	///
318	/// ### Examples
319	///
320	/// ```
321	/// use fp_library::types::*;
322	///
323	/// let lazy = ArcLazyConfig::new_lazy(Box::new(|| 42));
324	/// assert_eq!(*ArcLazyConfig::force(&lazy), 42);
325	/// ```
326	fn new_lazy<'a, A: 'a>(f: Box<Self::Init<'a, A>>) -> Self::Lazy<'a, A> {
327		Arc::new(LazyLock::new(f))
328	}
329
330	/// Creates a new fallible lazy cell from an initializer.
331	///
332	/// ### Type Signature
333	///
334	/// `forall e a. (Unit -> Result a e) -> TryLazy a e`
335	///
336	/// ### Type Parameters
337	///
338	/// * `A`: The type of the value.
339	/// * `E`: The type of the error.
340	///
341	/// ### Parameters
342	///
343	/// * `f`: The initializer thunk.
344	///
345	/// ### Returns
346	///
347	/// A new fallible lazy cell.
348	///
349	/// ### Examples
350	///
351	/// ```
352	/// use fp_library::types::*;
353	///
354	/// let lazy = ArcLazyConfig::new_try_lazy(Box::new(|| Ok::<i32, ()>(42)));
355	/// assert_eq!(ArcLazyConfig::force_try(&lazy), Ok(&42));
356	/// ```
357	fn new_try_lazy<'a, A: 'a, E: 'a>(f: Box<Self::TryInit<'a, A, E>>) -> Self::TryLazy<'a, A, E> {
358		Arc::new(LazyLock::new(f))
359	}
360
361	/// Forces evaluation and returns a reference.
362	///
363	/// ### Type Signature
364	///
365	/// `forall a. Lazy a -> a`
366	///
367	/// ### Type Parameters
368	///
369	/// * `A`: The type of the value.
370	///
371	/// ### Parameters
372	///
373	/// * `lazy`: The lazy cell to force.
374	///
375	/// ### Returns
376	///
377	/// A reference to the value.
378	///
379	/// ### Examples
380	///
381	/// ```
382	/// use fp_library::types::*;
383	///
384	/// let lazy = ArcLazyConfig::new_lazy(Box::new(|| 42));
385	/// assert_eq!(*ArcLazyConfig::force(&lazy), 42);
386	/// ```
387	fn force<'a, 'b, A: 'a>(lazy: &'b Self::Lazy<'a, A>) -> &'b A {
388		LazyLock::force(lazy)
389	}
390
391	/// Forces evaluation and returns a reference to the result.
392	///
393	/// ### Type Signature
394	///
395	/// `forall e a. TryLazy a e -> Result a e`
396	///
397	/// ### Type Parameters
398	///
399	/// * `A`: The type of the value.
400	/// * `E`: The type of the error.
401	///
402	/// ### Parameters
403	///
404	/// * `lazy`: The fallible lazy cell to force.
405	///
406	/// ### Returns
407	///
408	/// A result containing a reference to the value or error.
409	///
410	/// ### Examples
411	///
412	/// ```
413	/// use fp_library::types::*;
414	///
415	/// let lazy = ArcLazyConfig::new_try_lazy(Box::new(|| Ok::<i32, ()>(42)));
416	/// assert_eq!(ArcLazyConfig::force_try(&lazy), Ok(&42));
417	/// ```
418	fn force_try<'a, 'b, A: 'a, E: 'a>(lazy: &'b Self::TryLazy<'a, A, E>) -> Result<&'b A, &'b E> {
419		LazyLock::force(lazy).as_ref()
420	}
421}
422
423/// A lazily-computed, memoized value with shared semantics.
424///
425/// The computation runs at most once; subsequent accesses return the cached value.
426/// Cloning a `Lazy` shares the underlying cache - all clones see the same value.
427///
428/// ### Type Parameters
429///
430/// * `A`: The type of the computed value.
431/// * `Config`: The memoization configuration (determines Rc vs Arc).
432///
433/// ### Fields
434///
435/// * `0`: The internal lazy cell.
436///
437/// ### Examples
438///
439/// ```
440/// use fp_library::types::*;
441///
442/// let memo = Lazy::<_, RcLazyConfig>::new(|| 5);
443/// let shared = memo.clone();
444///
445/// // First force computes and caches:
446/// let value = memo.get();
447///
448/// // Second force returns cached value (shared sees same result):
449/// assert_eq!(shared.get(), value);
450/// ```
451pub struct Lazy<'a, A, Config: LazyConfig = RcLazyConfig>(pub(crate) Config::Lazy<'a, A>)
452where
453	A: 'a;
454
455impl<'a, A, Config: LazyConfig> Clone for Lazy<'a, A, Config>
456where
457	A: 'a,
458{
459	fn clone(&self) -> Self {
460		Self(self.0.clone())
461	}
462}
463
464impl<'a, A, Config: LazyConfig> Lazy<'a, A, Config>
465where
466	A: 'a,
467{
468	/// Gets the memoized value, computing on first access.
469	///
470	/// ### Type Signature
471	///
472	/// `forall a. Lazy a -> a`
473	///
474	/// ### Returns
475	///
476	/// A reference to the memoized value.
477	///
478	/// ### Examples
479	///
480	/// ```
481	/// use fp_library::types::*;
482	///
483	/// let memo = Lazy::<_, RcLazyConfig>::new(|| 42);
484	/// assert_eq!(*memo.get(), 42);
485	/// ```
486	pub fn get(&self) -> &A {
487		Config::force(&self.0)
488	}
489}
490
491impl<'a, A> Lazy<'a, A, RcLazyConfig>
492where
493	A: 'a,
494{
495	/// Creates a new Lazy that will run `f` on first access.
496	///
497	/// ### Type Signature
498	///
499	/// `forall a. (Unit -> a) -> Lazy a`
500	///
501	/// ### Type Parameters
502	///
503	/// * `F`: The type of the initializer closure.
504	///
505	/// ### Parameters
506	///
507	/// * `f`: The closure that produces the value.
508	///
509	/// ### Returns
510	///
511	/// A new `Lazy` instance.
512	///
513	/// ### Examples
514	///
515	/// ```
516	/// use fp_library::types::*;
517	///
518	/// let memo = Lazy::<_, RcLazyConfig>::new(|| 42);
519	/// assert_eq!(*memo.get(), 42);
520	/// ```
521	pub fn new<F>(f: F) -> Self
522	where
523		F: FnOnce() -> A + 'a,
524	{
525		Lazy(RcLazyConfig::new_lazy(Box::new(f)))
526	}
527}
528
529impl<'a, A> From<Thunk<'a, A>> for Lazy<'a, A, RcLazyConfig> {
530	fn from(eval: Thunk<'a, A>) -> Self {
531		Self::new(move || eval.run())
532	}
533}
534
535impl<'a, A> From<Trampoline<A>> for Lazy<'a, A, RcLazyConfig>
536where
537	A: Send,
538{
539	fn from(task: Trampoline<A>) -> Self {
540		Self::new(move || task.run())
541	}
542}
543
544impl<'a, A> Lazy<'a, A, ArcLazyConfig>
545where
546	A: 'a,
547{
548	/// Creates a new Lazy that will run `f` on first access.
549	///
550	/// ### Type Signature
551	///
552	/// `forall a. (Unit -> a) -> Lazy a`
553	///
554	/// ### Type Parameters
555	///
556	/// * `F`: The type of the initializer closure.
557	///
558	/// ### Parameters
559	///
560	/// * `f`: The closure that produces the value.
561	///
562	/// ### Returns
563	///
564	/// A new `Lazy` instance.
565	///
566	/// ### Examples
567	///
568	/// ```
569	/// use fp_library::types::*;
570	///
571	/// let memo = Lazy::<_, ArcLazyConfig>::new(|| 42);
572	/// assert_eq!(*memo.get(), 42);
573	/// ```
574	pub fn new<F>(f: F) -> Self
575	where
576		F: FnOnce() -> A + Send + 'a,
577	{
578		Lazy(ArcLazyConfig::new_lazy(Box::new(f)))
579	}
580}
581
582/// Single-threaded memoization alias.
583pub type RcLazy<'a, A> = Lazy<'a, A, RcLazyConfig>;
584
585/// Thread-safe memoization alias.
586pub type ArcLazy<'a, A> = Lazy<'a, A, ArcLazyConfig>;
587
588impl_kind! {
589	impl<Config: LazyConfig> for LazyBrand<Config> {
590		type Of<'a, A: 'a>: 'a = Lazy<'a, A, Config>;
591	}
592}
593
594impl<'a, A> Defer<'a> for Lazy<'a, A, RcLazyConfig>
595where
596	A: Clone + 'a,
597{
598	fn defer<FnBrand: 'a + CloneableFn>(f: <FnBrand as CloneableFn>::Of<'a, (), Self>) -> Self
599	where
600		Self: Sized,
601	{
602		RcLazy::new(move || f(()).get().clone())
603	}
604}
605
606impl SendDefer for LazyBrand<ArcLazyConfig> {
607	fn send_defer<'a, A>(
608		thunk: impl 'a
609		+ Fn() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
610		+ Send
611		+ Sync
612	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
613	where
614		A: Clone + Send + Sync + 'a,
615	{
616		ArcLazy::new(move || thunk().get().clone())
617	}
618}
619
620impl RefFunctor for LazyBrand<RcLazyConfig> {
621	/// Maps a function over the memoized value, where the function takes a reference.
622	///
623	/// ### Type Signature
624	///
625	/// `forall b a. RefFunctor (Lazy RcLazyConfig) => (a -> b, Lazy a RcLazyConfig) -> Lazy b RcLazyConfig`
626	///
627	/// ### Type Parameters
628	///
629	/// * `B`: The type of the result.
630	/// * `A`: The type of the value.
631	/// * `F`: The type of the function.
632	///
633	/// ### Parameters
634	///
635	/// * `f`: The function to apply.
636	/// * `fa`: The memoized value.
637	///
638	/// ### Returns
639	///
640	/// A new memoized value.
641	///
642	/// ### Examples
643	///
644	/// ```
645	/// use fp_library::{
646	///     brands::*,
647	///     classes::*,
648	///     types::*,
649	/// };
650	///
651	/// let memo = Lazy::<_, RcLazyConfig>::new(|| 10);
652	/// let mapped = LazyBrand::<RcLazyConfig>::map_ref(
653	///     |x: &i32| *x * 2,
654	///     memo,
655	/// );
656	/// assert_eq!(*mapped.get(), 20);
657	/// ```
658	fn map_ref<'a, B: 'a, A: 'a, F>(
659		f: F,
660		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
661	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
662	where
663		F: FnOnce(&A) -> B + 'a,
664	{
665		let fa = fa.clone();
666		let init: Box<dyn FnOnce() -> B + 'a> = Box::new(move || f(fa.get()));
667		Lazy(RcLazyConfig::new_lazy(init))
668	}
669}
670
671#[cfg(test)]
672mod tests {
673	use super::*;
674	use std::cell::RefCell;
675	use std::rc::Rc;
676
677	/// Tests that `Lazy` caches the result of the computation.
678	///
679	/// Verifies that the initializer is called only once.
680	#[test]
681	fn test_memo_caching() {
682		let counter = Rc::new(RefCell::new(0));
683		let counter_clone = counter.clone();
684		let memo = RcLazy::new(move || {
685			*counter_clone.borrow_mut() += 1;
686			42
687		});
688
689		assert_eq!(*counter.borrow(), 0);
690		assert_eq!(*memo.get(), 42);
691		assert_eq!(*counter.borrow(), 1);
692		assert_eq!(*memo.get(), 42);
693		assert_eq!(*counter.borrow(), 1);
694	}
695
696	/// Tests that `Lazy` shares the cache across clones.
697	///
698	/// Verifies that clones see the same value and don't recompute.
699	#[test]
700	fn test_memo_sharing() {
701		let counter = Rc::new(RefCell::new(0));
702		let counter_clone = counter.clone();
703		let memo = RcLazy::new(move || {
704			*counter_clone.borrow_mut() += 1;
705			42
706		});
707		let shared = memo.clone();
708
709		assert_eq!(*memo.get(), 42);
710		assert_eq!(*counter.borrow(), 1);
711		assert_eq!(*shared.get(), 42);
712		assert_eq!(*counter.borrow(), 1);
713	}
714
715	/// Tests thread safety of `ArcLazy`.
716	///
717	/// Verifies that `ArcLazy` can be shared across threads and computes only once.
718	#[test]
719	fn test_arc_memo_thread_safety() {
720		use std::sync::atomic::{AtomicUsize, Ordering};
721		use std::thread;
722
723		let counter = Arc::new(AtomicUsize::new(0));
724		let counter_clone = counter.clone();
725		let memo = ArcLazy::new(move || {
726			counter_clone.fetch_add(1, Ordering::SeqCst);
727			42
728		});
729
730		let mut handles = vec![];
731		for _ in 0..10 {
732			let memo_clone = memo.clone();
733			handles.push(thread::spawn(move || {
734				assert_eq!(*memo_clone.get(), 42);
735			}));
736		}
737
738		for handle in handles {
739			handle.join().unwrap();
740		}
741
742		assert_eq!(counter.load(Ordering::SeqCst), 1);
743	}
744
745	/// Tests creation from `Thunk`.
746	///
747	/// Verifies `From<Thunk>` works correctly.
748	#[test]
749	fn test_memo_from_eval() {
750		let eval = Thunk::new(|| 42);
751		let memo = RcLazy::from(eval);
752		assert_eq!(*memo.get(), 42);
753	}
754
755	/// Tests creation from `Trampoline`.
756	///
757	/// Verifies `From<Trampoline>` works correctly.
758	#[test]
759	fn test_memo_from_task() {
760		// Trampoline requires Send, so we use a Send-compatible value
761		let task = Trampoline::pure(42);
762		let memo = RcLazy::from(task);
763		assert_eq!(*memo.get(), 42);
764	}
765
766	/// Tests Defer implementation.
767	#[test]
768	fn test_defer() {
769		use crate::brands::RcFnBrand;
770		use crate::classes::defer::defer;
771		use crate::functions::cloneable_fn_new;
772
773		let memo: RcLazy<i32> =
774			defer::<RcLazy<i32>, RcFnBrand>(cloneable_fn_new::<RcFnBrand, _, _>(|_| {
775				RcLazy::new(|| 42)
776			}));
777		assert_eq!(*memo.get(), 42);
778	}
779
780	/// Tests SendDefer implementation.
781	#[test]
782	fn test_send_defer() {
783		use crate::brands::LazyBrand;
784		use crate::classes::send_defer::send_defer;
785
786		let memo: ArcLazy<i32> =
787			send_defer::<LazyBrand<ArcLazyConfig>, _, _>(|| ArcLazy::new(|| 42));
788		assert_eq!(*memo.get(), 42);
789	}
790}