Macro core_extensions::tokens_method
source · tokens_method!() { /* proc-macro */ }
Expand description
Does slice and iterator operations on tokens, passing the result to a callback macro.
§Elements
The elements that this operates on are token trees, which can be any of:
-
A macro parameter(eg:
$foo
) -
A literal
-
A pair of matching
[]
/()
/{}
(no matter what’s contained by the matched pair) -
An identifier
-
Punctuation
§Methods
These are the methods that this provides:
-
first
: Gets the first token tree. -
last
: Gets the last token tree. -
split_first
: Gets the first token tree, and the remaining ones. -
split_last
: Gets the last token tree, and the remaining ones. -
split_last_n
: Gets the last n token trees, and the remaining ones. -
split_at
: Gets the token trees before the nth one, and from it. -
get
: Gets the token(s) at an index or range. -
split
/split_terminator
/split_starter
: Splits the tokens with some needle tokens. -
zip_shortest
/zip_longest
: Return the token trees of every list iterated over in lockstep. -
iterate
: Nested iteration over multiple lists.
The methods that take integer arguments use
the <number>
syntax from gen_ident_range
§Iterators
This macro can iterate over both lists of token trees (eg: (foo bar baz)
),
and iteration functions (eg: range(0..10)
).
§Functions
Iteration functions can be used to generate tokens or transform a list of tokens.
These are the functions:
-
range
: Iterates over all the integers in a range, can be unbounded. -
gen_ident_range
: Generates identifiers by using thegen_ident_range
macro. -
chain
: Concatenates multiple iterators. -
take
: Takes some amount of elements from a possibly unbounded iterator. -
skip
: Skips elements from a possibly unbounded iterator. -
cycle
: Takes a bounded iterator and repeats it infinitely. -
repeat
: Repeats a bounded iterator some amount of times.
When an iterator function generates an unbounded amount of tokens, they must be constrained by another iterator to be used, otherwise producing a compile-time error to prevent the proc macro from running forever.
§Version compatibility
This macro requires Rust 1.45.0 to be invoked inside of a function.
§Examples
Examples that demonstrate properties common to all methods
§Macro parameters
This demonstrates how you can pass macro parameters to tokens_method
.
Note that because this example uses this macro in an expression, it requires at least Rust 1.45.0.
fn main() {
{
let arrays = split_array!(2 => 3, 5, 8, 5 + 8, 3 + 5 + 13, 34, 55);
assert_eq!(arrays, ([3, 5], [8, 13, 21, 34, 55]));
}
{
let arrays = split_array!(100 => 3, 5, 8, 5 + 8, 3 + 5 + 13, 34, 55);
const EMPTY: [i32; 0] = [];
assert_eq!(arrays, ([3, 5, 8, 13, 21, 34, 55], EMPTY));
}
}
#[macro_export]
macro_rules! split_array {
($split_at:literal => $($elem:expr),* $(,)?) => {
// `tokens_method` calls `__priv_split_array` with `foo bar` as the first arguments,
// passing the return value of `split_at` after them.
$crate::__::tokens_method!{
__priv_split_array!{foo bar}
split_at($split_at):
($($elem)*) // Note the lack of `,`!
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __priv_split_array {
(foo bar ($($left:expr)*) ($($right:expr)*)) => {
([$($left,)*], [$($right,)*])
}
}
#[doc(hidden)]
mod __ {
pub use core_extensions::tokens_method;
}
§first
Gets the first token tree.
If there are no elements, this produces a ()
.
This can take an unbounded iterator function, since it only gets the first element.
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(foo2(), "bar2");
assert_eq!(baz(), "qux");
}
macro_rules! expects_fooooo {
($func:ident $lit:literal (1000) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_fooooo` here
tokens_method!{
expects_fooooo!{ foo "bar" }
first:
(1000 20 30 (40 50))
}
tokens_method!{
expects_fooooo!{ foo2 "bar2" }
first:
range(1000..) // taking an unbounded iterator argument
}
macro_rules! expects_baaaz {
($func:ident $lit:literal ((1 2 3)) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_baaaz` here
tokens_method!{
expects_baaaz!{ baz "qux" }
first:
((1 2 3) 20 30 (40 50))
}
§last
Gets the last token tree.
If there are no elements, this produces a ()
.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(baz(), "qux");
}
macro_rules! expects_fooooo {
($func:ident $lit:literal (1000) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_fooooo` here
tokens_method!{
expects_fooooo!{ foo "bar" }
last:
(20 30 (40 50) 1000)
}
macro_rules! expects_baaaz {
($func:ident $lit:literal ((1 2 3)) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_baaaz` here
tokens_method!{
expects_baaaz!{ baz "qux" }
last:
(20 30 (40 50) (1 2 3))
}
§split_first
Gets the first token tree, and the remaining ones.
If there are no elements, this produces () ()
.
If there is only one element, this produces ($first_element) ()
.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(baz(), "qux");
}
macro_rules! expects_fooooo {
($func:ident $lit:literal (1000) (20 30 (40 50)) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_fooooo` here
tokens_method!{
expects_fooooo!{ foo "bar" }
split_first:
(1000 20 30 (40 50))
}
macro_rules! expects_baaaz {
($func:ident $lit:literal ((1 2 3)) (20 30 (40 50)) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_baaaz` here
tokens_method!{
expects_baaaz!{ baz "qux" }
split_first:
((1 2 3) 20 30 (40 50))
}
§split_last
Gets the last token tree, and the remaining ones.
If there are no elements, this produces () ()
.
If there is only one element, this produces () ($last_elemnent)
.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(baz(), "qux");
}
macro_rules! expects_fooooo {
($func:ident $lit:literal (20 30 (40 50)) (1000) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_fooooo` here
tokens_method!{
expects_fooooo!{ foo "bar" }
split_last:
(20 30 (40 50) 1000)
}
macro_rules! expects_baaaz {
($func:ident $lit:literal (20 30 (40 50)) ((1 2 3)) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_baaaz` here
tokens_method!{
expects_baaaz!{ baz "qux" }
split_last:
(20 30 (40 50) (1 2 3))
}
§split_last_n
Gets the last n token trees, and the remaining ones.
If there’s fewer than n token trees in the list,
this simply returns the list in () (here)
.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(baz(), "qux");
}
macro_rules! expects_fooooo {
($func:ident $lit:literal (20 30) ((40 50) 1000) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_fooooo` here
tokens_method!{
expects_fooooo!{ foo "bar" }
split_last_n(2):
(20 30 (40 50) 1000)
}
macro_rules! expects_baaaz {
($func:ident $lit:literal (10 20) (30 (40 50) (1 2 3)) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_baaaz` here
tokens_method!{
expects_baaaz!{ baz "qux" }
// Equivalent to `split_last_n(3)`
split_last_n(count(_ 1 (2 2 2))):
(10 20 30 (40 50) (1 2 3))
}
§split_at
Gets the token trees before the nth one, and from it.
If there’s fewer than n token trees in the list,
this simply returns the list in (here) ()
.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(baz(), "qux");
}
macro_rules! expects_fooooo {
($func:ident $lit:literal (20) (30 (40 50) 1000 2345) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_fooooo` here
tokens_method!{
expects_fooooo!{ foo "bar" }
split_at(1):
(20 30 (40 50) 1000 2345)
}
macro_rules! expects_baaaz {
($func:ident $lit:literal (20 30 (40 50)) (1000 2345) ) => {
fn $func() -> &'static str {
$lit
}
}
}
// `tokens_method` calls `expects_baaaz` here
tokens_method!{
expects_baaaz!{ baz "qux" }
// Equivalent to `split_at(3)`
split_at(count(_ 1 (2 2 2))):
(20 30 (40 50) 1000 2345)
}
§get
Gets the token(s) at an index (either an integer or a range).
IF the integer index is out of bounds, this outputs ()
.
IF the range is out of bounds, this outputs the elements at the in-bound indices (of the range).
If the input elements come from an unbounded iterator, the range must have an end bound.
§Example
use core_extensions::tokens_method;
macro_rules! expects_one {
(foo bar (6)) => {}
}
// `tokens_method` invokes `expects_one` here
tokens_method!{expects_one!{ foo bar } get(3): (2 3 (4 5) 6 7)}
// taking an unbounded iterator
tokens_method!{expects_one!{ foo bar } get(2): range(4..)}
// `count(_ 1 (2 2))` is equivalent to `3`
tokens_method!{expects_one!{ foo bar } get(count(_ 1 (2 2))): (2 3 (4 5) 6 7)}
macro_rules! expects_two {
(baz qux (3 (4 5)) ) => {}
}
// `tokens_method` calls `expects_two` here
tokens_method!{expects_two!{ baz qux } get(1..3): (2 3 (4 5) 6 7)}
tokens_method!{expects_two!{ baz qux } get(1..=2): (2 3 (4 5) 6 7)}
macro_rules! expects_three {
(baz qux (2 3 (4 5)) ) => {}
}
// `tokens_method` calls `expects_three` here
tokens_method!{expects_three!{ baz qux } get(0..3): (2 3 (4 5) 6 7)}
tokens_method!{expects_three!{ baz qux } get( ..3): (2 3 (4 5) 6 7)}
tokens_method!{expects_three!{ baz qux } get(0..=2): (2 3 (4 5) 6 7)}
tokens_method!{expects_three!{ baz qux } get( ..=2): (2 3 (4 5) 6 7)}
macro_rules! expects_four {
(baz qux (3 (4 5) 6 7) ) => {}
}
// `tokens_method` calls `expects_four` here
tokens_method!{expects_four!{ baz qux } get(1..): (2 3 (4 5) 6 7)}
tokens_method!{expects_four!{ baz qux } get(1..): (2 3 (4 5) 6 7)}
tokens_method!{
expects_four!{ baz qux }
get(1..=4):
chain((2 3 (4 5)) range(6..))
}
§split
Splits the tokens with some needle tokens.
If the needle is at the end of the tokens, this outputs a final ()
.
Eg: X
splits foo X bar X
into (foo) (bar) ()
.
If the needle is not found, this outputs all the tokens.
§Example
Note that because this example uses this macro in an expression, it requires at least Rust 1.45.0.
fn main() {
assert_eq!(
piped!(100 |> |x:u32| x + 1 |> |x:u32| x.to_string() ),
"101",
);
assert_eq!(piped!("foo" |> String::from |> repeat), "foofoofoofoo");
}
fn repeat<S: AsRef<str>>(s: S) -> String {
s.as_ref().repeat(4)
}
#[macro_export]
macro_rules! piped {
( $($tt:tt)* ) => {
$crate::__::tokens_method!(
$crate::__priv_piped!(hello)
split(|>):
($($tt)*)
)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __priv_piped {
(hello ($value:expr) $(($f:expr))* ) => ({
match $value {x => {
$( let x = $f(x); )*
x
}}
})
}
#[doc(hidden)]
pub mod __ {
pub use core_extensions::tokens_method;
}
§split_terminator
Splits the tokens with some needle tokens.
If the needle is at the end of the tokens, this does not output an additional ()
.
Eg: X
splits foo X bar X
into (foo) (bar)
.
If the needle is not found, this outputs all the tokens.
§Example
Note that because this example uses this macro in an expression, it requires at least Rust 1.45.0.
fn main() {
let expected = "hello99_99world";
// `++` can be used between strings
assert_eq!(concaten!("hello" ++ format!("{0}_{0}", 99) ++ "world"), expected);
// `++` can also terminate the argument list
assert_eq!(concaten!("hello" ++ format!("{0}_{0}", 99) ++ "world" ++), expected);
}
#[macro_export]
macro_rules! concaten {
( $($tt:tt)* ) => {
$crate::__::tokens_method!(
$crate::__priv_concaten!(hello)
split_terminator(++):
($($tt)*)
)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __priv_concaten {
(hello $(($f:expr))* ) => ({
let mut buff = $crate::__::String::new();
$(
buff.push_str($f.as_ref());
)*
buff
});
($($tt:tt)*) => { core_extensions::compile_error_stringify!{$($tt)*} }
}
#[doc(hidden)]
pub mod __ {
pub use core_extensions::tokens_method;
pub use std::string::String;
}
§split_starter
Splits the tokens with some needle tokens.
If the needle is at the start of the tokens, this does not output a ()
at the start.
Eg: X
splits X foo X bar
into (foo) (bar)
.
If the needle is not found, this outputs all the tokens.
§Example
Note that because this example uses this macro in an expression, it requires at least Rust 1.45.0.
fn main() {
let expected = Flags::Foo.or(Flags::Bar).or(Flags::Baz).or(Flags::Qux);
// `|` can be used between flags
assert_eq!(combine!(Foo | Bar | Flags::Baz.or(Flags::Qux) ), expected);
// `|` can also start the argument list
const PRE_FLAGS: Flags = combine!(| Foo | returns_flags() | Bar );
assert_eq!(PRE_FLAGS, expected);
}
const fn returns_flags()-> Flags {
combine!(Baz | Qux)
}
/// Allows using `Foo | Bar` syntax for Flags in a const context
/// (as of Rust 1.51.0, custom types can't overload the `|` operator in const contexts).
#[macro_export]
macro_rules! combine {
( $($tt:tt)* ) => {
$crate::__::tokens_method!(
$crate::__priv_combine!(world)
split_starter(|):
($($tt)*)
)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __priv_combine {
(world $($param:tt)* ) => (
$crate::Flags::Empty $( .or($crate::__priv_combine!(@flag $param)) )*
);
(@flag ($ident:ident)) => { $crate::Flags::$ident };
(@flag ($expression:expr)) => { $expression };
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct Flags(u32);
impl Flags {
pub const Empty: Self = Self(0);
pub const Foo: Self = Self(1);
pub const Bar: Self = Self(2);
pub const Baz: Self = Self(4);
pub const Qux: Self = Self(8);
pub const fn or(mut self, other: Self) -> Self {
self.0 |= other.0;
self
}
}
#[doc(hidden)]
pub mod __ {
pub use core_extensions::tokens_method;
}
§zip_shortest
Returns the token trees of every list iterated over in lockstep.
This returns as many token trees as the shortest list.
This is similar to lockstep iteration in macro_rules! macros, except that those require the lists to be the same length.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(foo(), "bar");
assert_eq!(baz(), "qux");
}
macro_rules! expected {
(
$func:ident $value:literal
((foo3) (bar3) (qux3))
((foo5) (bar5) (qux5))
((foo8) (bar8) (qux8))
((foo13) (bar13) (qux13))
((foo21) (bar21) (qux21))
) => {
fn $func() -> &'static str {
$value
}
}
}
// `tokens_method` calls `expected` here
tokens_method!{
expected!{foo "bar"}
zip_shortest:
(foo3 foo5 foo8 foo13 foo21)
(bar3 bar5 bar8 bar13 bar21)
(qux3 qux5 qux8 qux13 qux21)
}
// `tokens_method` calls `expected` here
tokens_method!{
expected!{baz "qux"}
zip_shortest:
(foo3 foo5 foo8 foo13 foo21)
(bar3 bar5 bar8 bar13 bar21)
// this list is truncated because it's longer than the others
(qux3 qux5 qux8 qux13 qux21 qux34 qux55)
}
macro_rules!
requires lockstep iteration to be over lists of the exact same length:
macro_rules! iteration {
([$($a:tt)*] [$($b:tt)*]) => {
bar!( $(($a $b))* )
}
}
while zip_shortest
truncates to the shortest list,
and zip_longest
fills in ()
for the shorter lists.
§zip_longest
Returns the token trees of every list iterated over in lockstep.
This returns as many token trees as the longest list,
filling in ()
for the shorter lists.
This is similar to lockstep iteration in macro_rules! macros, except that those require the lists to be the same length.
§Example
use core_extensions::tokens_method;
fn main() {
assert_eq!(baz(), "qux");
}
macro_rules! expected {
(
$func:ident $value:literal
((0) (bar3) (qux3))
((1) (bar5) (qux5))
((2) (bar8) (qux8))
((3) (bar13) (qux13))
((4) (bar21) (qux21))
((5) () (qux34))
((6) () (qux55))
) => {
fn $func() -> &'static str {
$value
}
}
}
// `tokens_method` calls `expected` here
tokens_method!{
expected!{baz "qux"}
zip_longest:
// Unbounded ranges only generate as many tokens as the longest finite iterator
range(0..)
(bar3 bar5 bar8 bar13 bar21)
(qux3 qux5 qux8 qux13 qux21 qux34 qux55)
}
§iterate
Nested iteration over multiple lists.
This can iterate over any amount of lists.
§Basic example
use core_extensions::tokens_method;
fn main() {
assert_eq!(single(), "111");
assert_eq!(double(), "222");
assert_eq!(triple(), "333");
}
macro_rules! assertion_single{
(
$func:ident $expr:literal
(foo bar baz)
) => {
fn $func() -> &'static str {
$expr
}
}
}
tokens_method!{
assertion_single!{single "111"}
iterate:
(foo bar baz)
}
macro_rules! assertion_double{
(
$func:ident $expr:literal
(
{ a } (foo bar baz)
{ b } (foo bar baz)
{ c } (foo bar baz)
)
) => {
fn $func() -> &'static str {
$expr
}
}
}
tokens_method!{
assertion_double!{double "222"}
iterate:
(a b c)
(foo bar baz)
}
macro_rules! assertion_triple{
(
$func:ident $expr:literal
(
{ 3 } (
{ a } (foo bar baz)
{ b } (foo bar baz)
{ c } (foo bar baz)
)
{ 5 } (
{ a } (foo bar baz)
{ b } (foo bar baz)
{ c } (foo bar baz)
)
{ 8 } (
{ a } (foo bar baz)
{ b } (foo bar baz)
{ c } (foo bar baz)
)
)
) => {
fn $func() -> &'static str {
$expr
}
}
}
tokens_method!{
assertion_triple!{triple "333"}
iterate:
(3 5 8)
(a b c)
(foo bar baz)
}
§Enum Example
This demonstrates a macro to declare an enum in which all the variants have the same fields.
homogeneous_enum!{
pub enum Foo { Bar, Baz, Qux }
fields = { a, b, c }
field_type = u32,
}
fn main() {
Foo::Bar{a: 3, b: 5, c: 8};
Foo::Baz{a: 13, b: 21, c: 34};
Foo::Qux{a: 55, b: 89, c: 144};
}
#[macro_export]
macro_rules! homogeneous_enum{
(
$(#[$attr:meta])*
$vis:vis enum $enum_name:ident {
$($variant:ident),* $(,)?
}
fields = { $($field:ident),* $(,)? }
field_type = $field_ty:ty $(,)?
) => {
$crate::__::tokens_method!{
$crate::__priv_homogeneous_enum!{
$(#[$attr])*
$vis,
$enum_name,
$field_ty,
}
iterate:
($($variant)*)
($($field)*)
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __priv_homogeneous_enum{
(
$(#[$attr:meta])*
$vis:vis,
$enum_name:ident,
$field_ty:ty,
($(
{$variant:ident} ($($field_ident:ident)*)
)*)
) => {
$(#[$attr])*
$vis enum $enum_name {
$(
$variant {
$( $field_ident: $field_ty, )*
},
)*
}
}
}
mod __ {
pub use core_extensions::tokens_method;
}
§range
iterator function
Iterates over a range, can be bounded or unbounded.
If the range is unbounded, it must be constrained by some other iterator, otherwise causing a compile-time error.
This uses
the <number>
syntax from gen_ident_range
for the range bounds.
§Example
use core_extensions::tokens_method;
macro_rules! assertion {
((0 1 2 3 4)) => {}
}
// `tokens_method` calls `assertion` here
tokens_method!{assertion!{} iterate: range(0..5)}
tokens_method!{assertion!{} iterate: range(..5)}
tokens_method!{assertion!{} iterate: range(0..=4)}
tokens_method!{assertion!{} iterate: range(..=4)}
// You can use `count(....)` to count token trees, using the count as a range bound.
tokens_method!{assertion!{} iterate: range(..count(_ _ _ _ _))}
macro_rules! assert_zip {
(((0) (a)) ((1) (b)) ((2) (c)) ((3) ((d f g))) ((4) ({h i j}))) => {}
}
// Both of these call `assert_zip` with the same tokens
tokens_method!{
assert_zip!{}
zip_shortest:
range(0..)
(a b c (d f g) {h i j})
}
tokens_method!{
assert_zip!{}
zip_longest:
range(0..)
(a b c (d f g) {h i j})
}
§gen_ident_range
iterator function
Generates identifiers by using the gen_ident_range
macro.
The range can be unbounded so long as it’s constrained by some other iterator,
§Example
use core_extensions::tokens_method;
macro_rules! assertion {
((pre_1 pre_2 pre_3 pre_4 pre_5)) => {}
}
// `tokens_method` calls `assertion` here
tokens_method!{
assertion!{}
iterate: gen_ident_range(for pre_* in 1..=5)
}
tokens_method!{
assertion!{}
iterate: gen_ident_range(for pre_* in 1..6)
}
tokens_method!{
assertion!{}
iterate: gen_ident_range(for pre_* in 1..=count(_ _ _ _ _))
}
// One way unbounded ranges can be used
macro_rules! assertion_zipped {
(((a) (foo0)) ((b) (foo1)) ((c) (foo2))) => {}
}
// `tokens_method` calls `assertion_zipped` here
tokens_method!{
assertion_zipped!{}
zip_shortest:
(a b c)
gen_ident_range(for foo* in 0..)
}
§chain
iterator function
Concatenates multiple iterators.
The iterators can be unbounded so long as chain
is constrained by some other iterator,
§Example
use core_extensions::tokens_method;
macro_rules! assertion {
((a b c 0 1 2)) => {}
}
// `tokens_method` calls `assertion` here
tokens_method!{
assertion!{}
iterate: chain((a b c) range(0..=2))
}
macro_rules! assertion_zipped {
(((0) (a)) ((1) (b)) ((2) (10)) ((3) (11))) => {};
}
// One way unbounded ranges can be used.
// `tokens_method` calls `assertion_zipped` here
tokens_method!{
assertion_zipped!{}
zip_shortest:
range(0..=3)
chain((a b) range(10..))
}
§take
iterator function
Takes some amount of elements from a possibly unbounded iterator.
§Example
use core_extensions::tokens_method;
macro_rules! assertion {
((a b 0 1 2)) => {}
}
// `tokens_method` calls `assertion` here
tokens_method!{
assertion!{}
iterate:
take(5, chain((a b) range(0..10)))
}
tokens_method!{
assertion!{}
iterate:
take(count(_ _ _ _ _), chain((a b) range(0..)))
}
§skip
iterator function
Skips elements from a possibly unbounded iterator.
§Example
use core_extensions::tokens_method;
macro_rules! assertion {
((f g 0 1 2)) => {}
}
// `tokens_method` calls `assertion` here
tokens_method!{
assertion!{}
iterate:
skip(5, chain((a b c d e f g) range(0..3)))
}
tokens_method!{
assertion!{}
iterate:
skip(count(_ _ _ _ _), chain((a b c d e f g) range(0..3)))
}
// passing an unbounded iterator to skip
tokens_method!{
assertion!{}
iterate:
take(5, skip(4, chain((b c d e f g) range(0..))))
}
§cycle
iterator function
Takes a bounded iterator and repeats it infinitely.
§Example
use core_extensions::tokens_method;
macro_rules! assertion {
(
((0) (a)) ((1) (b)) ((2) (c))
((0) (d)) ((1) (e)) ((2) (f))
((0) (g)) ((1) (h))
) => {}
}
tokens_method!{
assertion!{}
zip_shortest:
cycle(range(0..3))
(a b c d e f g h)
}
§repeat
iterator function
Repeats a bounded iterator some amount of times.
§Example
use core_extensions::tokens_method;
macro_rules! assertion_four_times {
((0 1 2 0 1 2 0 1 2 0 1 2)) => {}
}
// `tokens_method` calls `assertion_four_times` here
tokens_method!{
assertion_four_times!{}
iterate:
repeat(4, range(0..=2))
}
macro_rules! assertion_zero_times {
(()) => {}
}
// `tokens_method` calls `assertion_zero_times` here
tokens_method!{
assertion_zero_times!{}
iterate:
repeat(0, range(0..=2))
}