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 Result
s.
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)