Skip to content

Commit b5d699a

Browse files
committed
Add Readme
1 parent 75170f5 commit b5d699a

File tree

2 files changed

+361
-0
lines changed

2 files changed

+361
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 goandylok
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
# `comp-rs`
2+
3+
Pure-macro Do notation and List-comprehension for Option, Result and Iterator.
4+
5+
### [**Documentation**](https://goandylok.github.io/arraydeque/doc/arraydeque/index.html)
6+
7+
## Usage
8+
9+
First, add the following to your `Cargo.toml`:
10+
11+
```toml
12+
[dependencies]
13+
comp = "0.1"
14+
```
15+
16+
Next, add this to your crate root:
17+
18+
```rust
19+
#[macro_use]
20+
extern crate comp;
21+
```
22+
23+
## Example
24+
25+
`comp-rs` delivers three macros : *`option!`*, *`result!`* and *`iter!`*,
26+
which work in similar way.
27+
28+
### Iterator
29+
30+
```rust
31+
#[macro_use]
32+
extern crate comp;
33+
34+
let iter = iter! {
35+
let x <- 0..2;
36+
let y <- vec!['a', 'b'];
37+
(x, y)
38+
}
39+
40+
for x in iter {
41+
println!("{}", x);
42+
}
43+
44+
// Print (0, 'a') (0, 'b') (1, 'a') (1, 'b')
45+
```
46+
47+
### Option
48+
```rust
49+
let option = option! {
50+
let a <- Some(1);
51+
let b <- Some(2);
52+
a + b
53+
};
54+
55+
assert_eq!(option, Some(3));
56+
```
57+
58+
### Result
59+
60+
Unlike `Iterator` and `Option`, rust provided __*Question Mark*__ syntax to combine `Result`s.
61+
62+
Let's see how `comp-rs` make it more explicit and expressive.
63+
64+
#### Native way
65+
66+
```rust
67+
use std::fs::File;
68+
use std::io::prelude::*;
69+
70+
let content: Result<String> = {
71+
let mut f = try!(File::open("foo.txt"));
72+
let mut s = String::new();
73+
try!(f.read_to_string(&mut s));
74+
s
75+
};
76+
77+
```
78+
79+
#### Question mark
80+
81+
```rust
82+
use std::fs::File;
83+
use std::io::prelude::*;
84+
85+
let content: Result<String> = {
86+
let mut f = File::open("foo.txt")?;
87+
let mut s = String::new();
88+
f.read_to_string(&mut s)?;
89+
s
90+
};
91+
```
92+
93+
#### `comp-rs` way
94+
95+
```rust
96+
use std::fs::File;
97+
use std::io::prelude::*;
98+
99+
let content: Result<String> = result! {
100+
let mut f <- File::open("foo.txt");
101+
let mut s = String::new();
102+
let size <- f.read_to_string(&mut s);
103+
s
104+
};
105+
```
106+
107+
## Syntax
108+
109+
All of three macros always return wrapped type(`Option<T>`, `Result<T>` and
110+
`Iterator<Item=T>`), and yield the last expression.
111+
112+
### 1. Basic arrow(<-) syntax
113+
114+
#### Rules
115+
116+
```rust
117+
Macro Expand
118+
|
119+
option! {} | Some(())
120+
|
121+
option! { x; } | { x; Some(()) }
122+
|
123+
option! { x } | Some(x)
124+
|
125+
126+
Macro
127+
------------------------------------
128+
Expand
129+
130+
option! { let x <- Some(1); }
131+
------------------------------------
132+
Some(1).and_then(move |x| option!{})
133+
134+
option! { let x <- Some(1); x }
135+
------------------------------------
136+
Some(1).and_then(move |x| option!{ x })
137+
138+
option! { let mut x <- Some(1); x }
139+
------------------------------------
140+
Some(1).and_then(move |mut x| option!{ x })
141+
```
142+
143+
#### Example
144+
145+
```rust
146+
let option = option! {
147+
let a <- Some(1);
148+
let b <- Some(2);
149+
a + b
150+
};
151+
152+
// code above is expanded roughly into this
153+
154+
let option = {
155+
Some(1).and_then(move |a| {
156+
Some(2).and_then(move |b| {
157+
Some(a + b)
158+
})
159+
})
160+
};
161+
```
162+
163+
```rust
164+
let iter = iter! {
165+
let x <- 0..2;
166+
let y <- vec!['a', 'b'];
167+
(x, y)
168+
}
169+
170+
// code above is expanded roughly into this
171+
172+
let iter = {
173+
(0..2).into_iter().flat_map(move |x| {
174+
(vec!['a', 'b']).into_iter().flat_map(move |y| {
175+
::std::iter::once((x, y))
176+
})
177+
})
178+
};
179+
```
180+
181+
### 2. Yield
182+
183+
The last expression of the block will be yielded, similar to functions in rust.
184+
185+
```rust
186+
let iter = iter! {
187+
let x <- 0..2;
188+
let y <- vec!['a', 'b'];
189+
190+
(x, y) // <------- Yield
191+
}
192+
```
193+
194+
The block yields `()` While the last line is __*arrow statement*__ or statement
195+
with __*semicolon*__.
196+
197+
```rust
198+
let option: Option<()> = option! {
199+
let a <- Some(1);
200+
let b <- Some(2);
201+
};
202+
203+
let option: Option<()> = option! {
204+
let a <- Some(1);
205+
let b <- Some(2);
206+
a + b;
207+
};
208+
```
209+
210+
### 3. Pattern
211+
212+
In `comp-rs` pattern is supported as it should be.
213+
214+
#### Tuple
215+
216+
```rust
217+
let option = option! {
218+
let (x, y) <- Some((1, 2));
219+
(y, x)
220+
};
221+
222+
assert_eq!(option, Some((2, 1)));
223+
```
224+
225+
#### Struct
226+
227+
```rust
228+
struct Struct { x: usize };
229+
230+
let option = option! {
231+
let Struct { x } <- Some(Struct { x: 1 });
232+
x
233+
};
234+
235+
assert_eq!(option, Some(1));
236+
```
237+
238+
#### Ignore
239+
240+
```rust
241+
let option = option! {
242+
let _ <- Some(1);
243+
};
244+
```
245+
246+
#### ... And So On
247+
248+
### 4. If-Guard
249+
250+
If-Guard is specific for `iter!` which translate condition into `filter()`.
251+
252+
It wrap the following code into a block and call `filter()` on it.
253+
254+
```rust
255+
let iter = iter! {
256+
let x <- 0..4;
257+
let y <- 2..6;
258+
259+
if x == y;
260+
261+
(x, y)
262+
};
263+
264+
let expected = vec![(2, 2), (3, 3)];
265+
assert!(expected, iter.collect::<Vec<_>>());
266+
```
267+
268+
### 5. Statement & Block
269+
270+
Statements and blocks are also supported.
271+
272+
```rust
273+
// statement
274+
let iter = iter! {
275+
let start = 5;
276+
let end;
277+
end = start * 3;
278+
279+
// 5, 6, ..., 13, 14
280+
let x <- start..end;
281+
x
282+
};
283+
let expected = 5..15;
284+
assert!(iter.eq(expected.into_iter()));
285+
```
286+
```rust
287+
let iter = iter! {
288+
let mut a <- 0..5;
289+
290+
// block
291+
{
292+
fn double(x: u8) -> u8 { x * 2}
293+
let tmp = double(a);
294+
a = tmp;
295+
};
296+
297+
// unsafe block
298+
let count = unsafe {
299+
static mut CALL_COUNT: u8 = 0;
300+
CALL_COUNT += 1;
301+
CALL_COUNT
302+
};
303+
304+
(a, count)
305+
};
306+
let expected = vec![(0, 1), (2, 2), (4, 3), (6, 4), (8, 5)];
307+
assert!(iter.eq(expected.into_iter()));
308+
```
309+
310+
### Array
311+
312+
`Array` in rust behaves various from other collections. It only iterates its
313+
content by reference.
314+
So `iter!` always bind *references* by `arrow(<-)` syntax, then you need to
315+
*deref* the binded value.
316+
And since one can't move any value out of an `array`, array should be place
317+
outside the macro to satisfy lifetime.
318+
319+
```rust
320+
let array = [0, 1, 2, 3];
321+
let iter = iter! {
322+
let x <- array;
323+
let y <- *x..4;
324+
(*x, y)
325+
};
326+
let expected = vec![(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2),
327+
(2, 3), (3, 3)];
328+
assert!(expected, iter.collect::<Vec<_>>());
329+
```
330+
331+
## Contribution
332+
333+
All kinds of contribution are welcomed.
334+
335+
- **Issus.** Feel free to open an issue when you find typos, bugs, or have any question.
336+
- **Pull requests**. New collection, better implementation, more tests, more documents and typo fixes are all welcomed.
337+
338+
## License
339+
340+
Licensed under MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

0 commit comments

Comments
 (0)