Skip to content

Pure-macro Do notation and List-comprehension for Option, Result and Iterator.

License

Notifications You must be signed in to change notification settings

andylokandy/comp-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

comp-rs

Build Status crates.io docs.rs

Pure-macro Do notation and List-comprehension for Option, Result and Iterator.

It provides syntax extensions to easily combind wrapper type (Option, Result and Iterator), which seems like for-comprehension in scala or Do notation in haskell.

Usage

First, add the following to your Cargo.toml:

[dependencies]
comp = "*"

Next, add this to your crate root:

#[macro_use]
extern crate comp;

Example

comp-rs delivers three macros : option!, result! and iter!, transforming the arrow(<-) statements into FP bind (flat_map).

Iterator

#[macro_use]
extern crate comp;

let iter = iter! {
  let x <- 0..2u8;
  let y <- vec!['a', 'b'];
  (x, y)
};

for x in iter {
  println!("{:?}", x);
}

// Print (0, 'a') (0, 'b') (1, 'a') (1, 'b')

It can be written like generator expressions in python:

# Python
values = [6, 2, 9, 4, -1, 33, 87, 23]
result = (x*x for x in values if x < 10)

or in scala

// Scala
val values = Array(6, 2, 9, 4, -1, 33, 87, 23)
val result = for(x <- values if x < 10) yield x*x

in Rust

// comp-rs
// The result is of type FlatMap and also lazy, like Python's generator expressions.
let values = vec![6, 2, 9, 4, -1, 33, 87, 23];
let result = iter!{let x <- values; if x < 10; x*x};

Option

#[macro_use]
extern crate comp;

let option = option! {
  let a <- Some(1);
  let b <- Some(2);
  a + b
};

assert_eq!(option, Some(3));

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

#[macro_use]
extern crate comp;

use std::fs::File;
use std::io;
use std::io::prelude::*;

// try!() macro must be wrap into a function
fn content() -> io::Result<String> {
    let mut f = try!(File::open("foo.txt"));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

Question mark

#[macro_use]
extern crate comp;

use std::fs::File;
use std::io;
use std::io::prelude::*;

// '?' mark must be wrap into a function
fn content() -> io::Result<String> {
    let mut f = File::open("foo.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}

result! way

#[macro_use]
extern crate comp;

use std::fs::File;
use std::io;
use std::io::prelude::*;

let content: io::Result<String> = result! {
  let mut f <- File::open("foo.txt");
  let mut s = String::new();
  let _ <- f.read_to_string(&mut s);
  s
};

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)

About

Pure-macro Do notation and List-comprehension for Option, Result and Iterator.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages