DanielKeep.github.io icon indicating copy to clipboard operation
DanielKeep.github.io copied to clipboard

error: `$inits:expr` may be followed by `...`, which is not allowed for `expr` fragments

Open HongbinZhou opened this issue 8 years ago • 1 comments

Hi, first thanks a lot for your helpful doc: https://danielkeep.github.io/practical-intro-to-macros.html !

I got build error: (using rustc 1.19.0-nightly (03abb1bd7 2017-06-13))

error: `$inits:expr` may be followed by `...`, which is not allowed for `expr` fragments
 --> /home/z/code/learn_rust/fib.rs:2:40
  |
2 |     ( a[n]: $sty:ty = $($inits:expr),+ ... $recur:expr ) => {
  |                                        ^^^

when tried the code:

macro_rules! recurrence {
    ( a[n]: $sty:ty = $($inits:expr),+ ... $recur:expr ) => {
        {
            /*
                What follows here is *literally* the code from before,
                cut and pasted into a new position.  No other changes
                have been made.
            */

            use std::ops::Index;

            struct Recurrence {
                mem: [u64; 2],
                pos: usize,
            }

            struct IndexOffset<'a> {
                slice: &'a [u64; 2],
                offset: usize,
            }

            impl<'a> Index<usize> for IndexOffset<'a> {
                type Output = u64;

                #[inline(always)]
                fn index<'b>(&'b self, index: usize) -> &'b u64 {
                    use std::num::Wrapping;

                    let index = Wrapping(index);
                    let offset = Wrapping(self.offset);
                    let window = Wrapping(2);

                    let real_index = index - offset + window;
                    &self.slice[real_index.0]
                }
            }

            impl Iterator for Recurrence {
                type Item = u64;

                #[inline]
                fn next(&mut self) -> Option<u64> {
                    if self.pos < 2 {
                        let next_val = self.mem[self.pos];
                        self.pos += 1;
                        Some(next_val)
                    } else {
                        let next_val = {
                            let n = self.pos;
                            let a = IndexOffset { slice: &self.mem, offset: n };
                            (a[n-1] + a[n-2])
                        };

                        {
                            use std::mem::swap;

                            let mut swap_tmp = next_val;
                            for i in (0..2).rev() {
                                swap(&mut swap_tmp, &mut self.mem[i]);
                            }
                        }

                        self.pos += 1;
                        Some(next_val)
                    }
                }
            }

            Recurrence { mem: [0, 1], pos: 0 }
        }
    };
}

fn main() {
    let fib = recurrence![a[n]: u64 = 0, 1 ... a[n-1] + a[n-2]];

    for e in fib.take(10) { println!("{}", e) }
}

HongbinZhou avatar Jun 26 '17 09:06 HongbinZhou

It's just the complier prevents you from doing so. Early(relatively to now) version of complier gives a warning, and another version after that gives a error.

lazystitan avatar Jul 05 '22 17:07 lazystitan