1#[macro_export]
14macro_rules! do_ {
15 ($F:ty; $e:expr) => {
17 $e
18 };
19 ($F:ty; $x:ident = $e:expr; $($rest:tt)+) => {
21 <$F as $crate::chain::Chain>::chain($e, |$x| {
22 $crate::do_!($F; $($rest)+)
23 })
24 };
25}
26
27#[macro_export]
41macro_rules! ado_ {
42 ($F:ty; $x:ident = $e:expr; yield $body:expr) => {
44 <$F as $crate::functor::Functor>::fmap($e, |$x| $body)
45 };
46 ($F:ty; $x1:ident = $e1:expr; $x2:ident = $e2:expr; yield $body:expr) => {
48 <$F as $crate::apply::Apply>::ap(
49 <$F as $crate::functor::Functor>::fmap($e1, |$x1| move |$x2| $body),
50 $e2,
51 )
52 };
53 ($F:ty;
55 $x1:ident = $e1:expr;
56 $x2:ident = $e2:expr;
57 $x3:ident = $e3:expr;
58 yield $body:expr
59 ) => {
60 <$F as $crate::apply::Apply>::ap(
61 <$F as $crate::apply::Apply>::ap(
62 <$F as $crate::functor::Functor>::fmap($e1, |$x1| move |$x2| move |$x3| $body),
63 $e2,
64 ),
65 $e3,
66 )
67 };
68 ($F:ty;
70 $x1:ident = $e1:expr;
71 $x2:ident = $e2:expr;
72 $x3:ident = $e3:expr;
73 $x4:ident = $e4:expr;
74 yield $body:expr
75 ) => {
76 <$F as $crate::apply::Apply>::ap(
77 <$F as $crate::apply::Apply>::ap(
78 <$F as $crate::apply::Apply>::ap(
79 <$F as $crate::functor::Functor>::fmap($e1, |$x1| {
80 move |$x2| move |$x3| move |$x4| $body
81 }),
82 $e2,
83 ),
84 $e3,
85 ),
86 $e4,
87 )
88 };
89}
90
91#[cfg(test)]
92mod tests {
93 use crate::applicative::Applicative;
94 use crate::hkt::OptionF;
95 #[cfg(any(feature = "std", feature = "alloc"))]
96 use crate::hkt::VecF;
97
98 #[test]
99 fn do_option_some() {
100 let result = do_! { OptionF;
101 x = Some(1);
102 y = Some(x + 1);
103 OptionF::pure(x + y)
104 };
105 assert_eq!(result, Some(3));
106 }
107
108 #[test]
109 fn do_option_none() {
110 let result: Option<i32> = do_! { OptionF;
111 x = Some(1);
112 _y = None::<i32>;
113 OptionF::pure(x)
114 };
115 assert_eq!(result, None);
116 }
117
118 #[test]
119 fn do_option_single() {
120 let result = do_! { OptionF;
121 Some(42)
122 };
123 assert_eq!(result, Some(42));
124 }
125
126 #[test]
127 fn do_vec() {
128 let result = do_! { VecF;
129 x = vec![1, 2];
130 y = vec![10, 20];
131 VecF::pure(x + y)
132 };
133 assert_eq!(result, vec![11, 21, 12, 22]);
134 }
135
136 #[test]
137 fn ado_option_1() {
138 let result = ado_! { OptionF;
139 x = Some(5);
140 yield x * 2
141 };
142 assert_eq!(result, Some(10));
143 }
144
145 #[test]
146 fn ado_option_2() {
147 let result = ado_! { OptionF;
148 x = Some(1);
149 y = Some(2);
150 yield x + y
151 };
152 assert_eq!(result, Some(3));
153 }
154
155 #[test]
156 fn ado_option_2_none() {
157 let result = ado_! { OptionF;
158 x = Some(1);
159 y = None::<i32>;
160 yield x + y
161 };
162 assert_eq!(result, None);
163 }
164
165 #[test]
166 fn ado_option_3() {
167 let result = ado_! { OptionF;
168 x = Some(1);
169 y = Some(2);
170 z = Some(3);
171 yield x + y + z
172 };
173 assert_eq!(result, Some(6));
174 }
175
176 #[test]
177 fn ado_option_4() {
178 let result = ado_! { OptionF;
179 a = Some(1);
180 b = Some(2);
181 c = Some(3);
182 d = Some(4);
183 yield a + b + c + d
184 };
185 assert_eq!(result, Some(10));
186 }
187
188 #[test]
189 fn ado_vec_2() {
190 let result = ado_! { VecF;
191 x = vec![1, 2];
192 y = vec![10, 20];
193 yield x + y
194 };
195 assert_eq!(result, vec![11, 21, 12, 22]);
196 }
197}