Giter Site home page Giter Site logo

velcro's Introduction

Velcro

Build Status

A set of macros for conveniently initializing collections from Rust's std and iterators. All of the macros support the unary .. operator which "spreads" the values of another collection or iterator.

velcro::vec! is a drop-in replacement for std::vec!. All functionality of the std macro is supported without overhead, but it also supports spreading values with the .. operator.

Examples

use velcro::{hash_map, iter, vec};

assert_eq!(vec![0, 1, ..(2..7)], vec![0, 1, 2, 3, 4, 5, 6]);

let other = vec![3, 4, 5];
assert_eq!(vec![0, 1, 2, ..&other, 6], vec![0, 1, 2, 3, 4, 5, 6]);

let whitespace = iter![' ', '\t', '\r', '\n'];
let map = hash_map! {
    ..('0'..='9'): "digit",
    ..('a'..='z'): "lower",
    ..('A'..='Z'): "upper",
    ..whitespace: "whitespace",
    '.': "punctuation",
    ',': "punctuation",
};

assert_eq!(map[&'x'], "lower");
assert_eq!(map[&'\r'], "whitespace");
assert_eq!(map[&'.'], "punctuation");

Help

For help, questions or to report an issue, please use the Github issue tracker.

velcro's People

Contributors

aeryz avatar dbanty avatar peterjoel avatar rottedfrog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

velcro's Issues

Spread map values

Currently .. is supported in maps for keys, but not values. It would be nice to be able to do this:

let map = hash_map! { 
    ..(0..5): ..(10..)
}

Which would give the same result as:

let map = (0..5).into_iter().zip(10..).collect::<HashMap<_, _>>();

May need to consider if it is an error if the number of keys exceeds number of values or vice versa.

It doesn't really make sense to spread values when the key is not also spread, so this should be an error:

let map = hash_map! { 
    0: ..(10..)
}

Implement `linked_list!` and `linked_list_from!`

Not commonly used, but LinkedList support can be added for completeness.

The implementation of hash_set can be used for reference. A lot of the heavy lifting is in SeqInput which can be reused.

Code gen for fixed length vector does not work with ranges

This works:

let a = [1, 2, 3, 4].iter().copied();
let v = vec![..a; 4];

But this does not:

let v = vec![..(1..=4); 4];

Error:

error[E0599]: no method named `into_iter` found for type `i32` in the current scope
 --> velcro/examples/vec_repeat.rs:5:13
  |
5 |     let v = velcro::vec![..(1_i32..5_i32); 4];
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `i32`

The generated code is:

let v = 1_i32..5_i32.into_iter().take(4).collect::<::std::vec::Vec<_>>();

It's trying to make an iterator from 5 not from 1..5.

Compile error with latest syn crate

syn version 1.0.58 breaks velcro due to a change in how it exposes "internal" modules.

In this commit:
dtolnay/syn@957840e

The error is:

error[E0433]: failed to resolve: could not find `export` in `syn`
   --> /home/peter/.cargo/registry/src/github.com-1ecc6299db9ec823/velcro_macros-0.5.1/src/lib.rs:100:18
    |
100 |     let output = parse_raw_macro_input!(input as BTreeMapInput<ConvertInto>).into_output();
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in `syn::export`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Spread maps into maps

It would be nice to be able to do this:

let map1 = hash_map! { 
    ..(0..5): 1,
    ..(5..10): 2,
    10: 10,
}

let map2 = hash_map! {
    ..map1,  // <-- currently not supported
    ..(11..20): 20,
}

Comment/question/suggestion regarding `..` in `hash_map!` macro

To me, velcro's use of .. is not great:

let map = hash_map! {
    ..('0'..='9'): "digit",
    ..('a'..='z'): "lower",
};

From https://doc.rust-lang.org/reference/expressions/range-expr.html

1..2;   // std::ops::Range
3..;    // std::ops::RangeFrom
..4;    // std::ops::RangeTo
..;     // std::ops::RangeFull
5..=6;  // std::ops::RangeInclusive
..=7;   // std::ops::RangeToInclusive

I'm wondering, how does velcro's current use of .. compare with the above, if at all? I don't see a convincing connection, from an API design point of view. To me, it feels like a stretch.

Would you consider the following syntax instead? It seems more natural to me:

let map = hash_map! {
  '0'..='9' : "digit",
  'a'..='z' : "lower",
};

Expressions containing paths are not accepted by macros

E.g.

use velcro::hash_map;

fn main() {
    let map = hash_map! {
        String::from("foo"): 1,
    };
    println!("map = {:?}", map);
}

Produces compile error:

error: expected expression
 --> examples/so.rs:5:15
  |
5 |         String::from("foo"): 1,
  |               ^^

Support type ascription in nightly

This may just work out of the box (I haven't yet tried it). But parentheses will definitely be needed, in which case we need to remove extra parentheses in generated code to prevent warnings, as we do for expressions containing ranges.

The same code should be generated in stable, but we need to make sure that the proper errors are produced.

Implement `array!` and `array_from!`

Array initialiizer macros.

Usage / test cases:

  • array![0,1,2,3] => [0,1,2,3]
  • array![..(0..=3)] => compile error - size must be given when using spread operator
  • array_from![0,1,2,3] => [0.into(), 1.into(), 2.into(), 3.into()] (and the same treatment for all examples below)
  • array![1; 4] => [1, 1, 1, 1] (not [1; 4] because we don't want to require Copy)
  • array![1; non_constant_var] => compile error - length must be constant
  • array![0, 1; 4] => Need to decide on one of:
    • panic - not enough elements
    • compile error - not enough elements (I'm currently favouring this option)
    • [0,1,0,1] (repeat the sequence)
    • [0,1,1,1] (repeat final element)
  • array![..(0..100); 4] => [0,1,2,3] (no error on too many elements when the last arg is a spread)
  • array![0, 1, 2, 3, ..(0..100); 4] => panic - too many elements (the array was already "full" before the final spread)
  • array![0, 1, ..(2..5), ..(0..100); 4] => panic - too many elements (the array was already "full" before the final spread)
  • array![0, 1, ..(2..); 4] => [0,1,2,3]
  • array![..(0..2); 4] => panic - not enough elements
  • array![0, ..(1..2); 4] => panic - not enough elements

Implementation:

  • This will require a little refactoring of VecInput so that its internals can be re-used.
  • It should be ok for the macro to accept any expression for the length. If the expression is not constant, the generated code should produce a suitable error without extra effort.
  • special cases for:
    • array![0,1,2,3] (no length specified)
    • array![1; 4] (repeat given element)
  • the other variants can write to a [MaybeUninit<T>; n] from a sequence of iterators.
  • If the length is larger than the number of provided elements, it often will not be possible to detect until runtime. It should:
    • panic, with a suitable error message
    • before panic, clean up the partially initialized array to avoid memory leaks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.