comp-rs
Pure-macro Do notation and List-comprehension for Option, Result and Iterator.
It provides syntax extensions separately for the three types above, which look like
for-comprehension in scala or Do notation in haskell.
Documentation
Usage
First, add the following to your Cargo.toml:
[]
= "0.1"
Next, add this to your crate root:
extern crate comp;
Example
comp-rs delivers three macros : option!, result! and iter!,
transforming the arrow(<-) statements into FP bind (flat_map).
Iterator
extern crate comp;
let iter = iter!
for x in iter
// Print (0, 'a') (0, 'b') (1, 'a') (1, 'b')
Option
extern crate comp;
let option = option! ;
assert_eq!;
Result
Unlike Iterator and Option, rust provides Question Mark syntax to combine Results.
Let's see how comp-rs makes it more explicit and expressive.
Native way
use File;
use *;
let content: = ;
Question mark
use File;
use *;
let content: = ;
comp-rs way
extern crate comp;
use File;
use *;
let content: = result! ;
Syntax
All three macros return wrapped type(Option<T>, Result<T> and
Iterator<Item=T>), and yield the last expression.
Syntax: (sentence)* ; expression
sentence can be:
let pattern <- expression;: bind expression to pattern.if filter_expression;: filter by condition, and jump over when not satisfied.statement;: let assignment, value assignment, etc.{...}: block and unsafe block.
Syntax Detail
1. Basic arrow(<-) syntax
Rules
Macro Expand
|
option! | Some
|
option! |
|
option! | Some
|
Macro
------------------------------------
Expand
option!
------------------------------------
Some.and_then
option!
------------------------------------
Some.and_then
option!
------------------------------------
Some.and_then
Example
let option = option! ;
// code above is expanded roughly into this
let option = ;
let iter = iter!
// code above is expanded roughly into this
let iter = ;
2. Yield
The last expression of the block will be yielded, similar to functions in rust.
let iter = iter!
The block yields () while the last line is arrow statement or statement
with semicolon.
let option: = option! ;
let option: = option! ;
3. Pattern
In comp-rs, pattern is supported as it should be.
Tuple
let option = option! ;
assert_eq!;
Struct
;
let option = option! ;
assert_eq!;
Ignore
let option = option! ;
... And So On
4. If-Guard
If-Guard is specific for iter! which translates condition into filter().
It wraps the following code into a block and call filter() on it.
let iter = iter! ;
let expected = vec!;
assert!;
5. Statement & Block
Statements and blocks are also supported.
// statement
let iter = iter! ;
let expected = 5..15;
assert!;
let iter = iter! ;
let expected = vec!;
assert!;
Array
Array in rust behaves differently from other collections. It only iterates its
content by reference.
So iter! always binds references in arrow(<-) syntax, then you need to
deref the bound value.
And since one can't move any value out of an array, array should be placed
outside the macro to satisfy lifetime.
let array = ;
let iter = iter! ;
let expected = vec!;
assert!;
Contribution
All kinds of contribution are welcome.
- Issue Feel free to open an issue when you find typos, bugs, or have any question.
- Pull requests. Better implementation, more tests, more documents and typo fixes are all welcome.
License
Licensed under MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)