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