Không; kết quả của một macro phải là một cấu trúc ngữ pháp hoàn chỉnh như một biểu thức hoặc một mục. Bạn hoàn toàn không thể có các bit cú pháp ngẫu nhiên như dấu phẩy hoặc dấu ngoặc đóng.
Bạn có thể giải quyết vấn đề này bằng cách không xuất ra bất kỳ thứ gì cho đến khi bạn có biểu thức hoàn chỉnh, cuối cùng. Kìa!
#![feature(trace_macros)]
macro_rules! pascal_impl {
/*
The input to this macro takes the following form:
```ignore
(
// The current output accumulator.
($($out:tt)*);
// The current additive prefix.
$prefix:expr;
// The remaining, comma-terminated elements.
...
)
```
*/
/*
Termination condition: there is no input left. As
such, dump the output.
*/
(
$out:expr;
$_prefix:expr;
) => {
$out
};
/*
Otherwise, we have more to scrape!
*/
(
($($out:tt)*);
$prefix:expr;
$e:expr, $($rest:tt)*
) => {
pascal_impl!(
($($out)* $prefix+$e,);
$prefix+$e;
$($rest)*
)
};
}
macro_rules! pascal {
($($es:expr),+) => { pascal_impl!((); 0; $($es),+,) };
}
trace_macros!(true);
fn main() {
println!("{:?}", pascal!(1, 2, 3, 4));
}
Note: Để sử dụng này trên một trình biên dịch ổn định, bạn sẽ cần phải xoá #![feature(trace_macros)]
và trace_macros!(true);
dòng. Mọi thứ khác sẽ ổn thôi.
Điều này không là nó đệ quy munches đi tại đầu vào, đi qua các phần (và có khả năng ngữ nghĩa không hợp lệ) đầu ra như đầu vào lên tầm cao mới của đệ quy. Điều này cho phép chúng tôi xây dựng một "danh sách mở", mà chúng tôi không thể làm khác.
Sau đó, khi chúng tôi không có dữ liệu đầu vào, chúng tôi chỉ diễn giải lại phần đầu ra một phần của chúng tôi dưới dạng biểu thức hoàn chỉnh và ... xong.
Lý do tôi bao gồm các công cụ truy tìm là để tôi có thể hiển thị cho bạn những gì nó trông giống như khi nó chạy:
pascal! { 1 , 2 , 3 , 4 }
pascal_impl! { () ; 0 ; 1 , 2 , 3 , 4 , }
pascal_impl! { (0 + 1 ,) ; 0 + 1 ; 2 , 3 , 4 , }
pascal_impl! { (0 + 1 , 0 + 1 + 2 ,) ; 0 + 1 + 2 ; 3 , 4 , }
pascal_impl! { (0 + 1 , 0 + 1 + 2 , 0 + 1 + 2 + 3 ,) ; 0 + 1 + 2 + 3 ; 4 , }
pascal_impl! { (0 + 1 , 0 + 1 + 2 , 0 + 1 + 2 + 3 , 0 + 1 + 2 + 3 + 4 ,) ; 0 + 1 + 2 + 3 + 4 ; }
Và kết quả là:
(1, 3, 6, 10)
Một điều cần phải nhận thức của : số lượng lớn các số nguyên nguyên không chú thích có thể gây ra sự gia tăng số lần biên dịch ấn tượng. Nếu điều này xảy ra, bạn có thể giải quyết nó bằng cách chỉ cần chú thích tất cả của các chữ số nguyên của bạn (như 1i32
).