Vâng, có hai cách.
Nếu bạn muốn phân tích cú pháp này chính xác, thì bạn sẽ cần sử dụng muncher. Vì vậy, một cái gì đó như:
macro_rules! re_export {
() => {};
(
pub fn $i:ident($($arg:ident: $argty:ty)*) -> $ret:ty;
$($tail:tt)*
) => {
extern {
pub fn $i($($arg: $argty),*) -> $ret;
}
re_export! { $($tail)* }
};
(
pub fn $i:ident($($arg:ident: $argty:ty)*);
$($tail:tt)*
) => {
extern {
pub fn $i($($arg: $argty),*);
}
re_export! { $($tail)* }
};
}
Điều này liên quan đến việc phá vỡ một chữ ký chức năng tại một thời điểm, xử lý đệ quy. Đây là cách phân tích cú pháp linh hoạt nhất, nhưng không có nghĩa là bạn có thể chạy ngược lại giới hạn đệ quy macro. Giới hạn mặc định là 64, vì vậy nếu bạn có nhiều đầu vào hơn, bạn sẽ cần nhiều lệnh gọi macro cấp cao nhất hoặc bạn sẽ phải tăng giới hạn đệ quy theo cách thủ công bằng cách thêm thuộc tính #![recursion_limit="128"]
vào thùng của bạn.
Cách khác là thay đổi cú pháp sao cho bạn chia nhỏ rồi xử lý chữ ký theo hai bước. Để làm điều này, bạn phải có một số loại cú pháp cấp cao nhất thường xuyên cho chữ ký. Ví dụ:
macro_rules! re_export {
($({$($sigs:tt)*})*) => {
$(
re_export! { @fn $($sigs)* }
)*
};
(@fn pub fn $i:ident($($arg:ident: $argty:ty),*) -> $ret:ty) => {
extern {
pub fn $i($($arg: $argty),*) -> $ret;
}
};
(@fn pub fn $i:ident($($arg:ident: $argty:ty),*)) => {
extern {
pub fn $i($($arg: $argty),*);
}
};
}
Ở đây, chúng tôi quấn từng chữ ký hàm vào {...}
s. Điều này là do các nhóm đối sánh ((...)
, [...]
và {...}
) cho phép macro_rules!
khớp nội dung của chúng một cách mù quáng mà không cần phải hiểu chúng. Điều này cho phép chúng tôi kết hợp các chữ ký chức năng bất thường theo cách thông thường. Việc mở rộng cấp cao nhất chỉ đơn giản là chuyển tiếp mỗi chữ ký hàm riêng lẻ trở lại chính nó để xử lý thực tế. @fn
chỉ là một dấu hiệu internal rule để đảm bảo chúng tôi chọn đúng quy tắc trong khi đệ quy.
này không có giới hạn đệ quy tương tự mà trước đó không ... nhưng đòi hỏi bạn phải sử dụng một cú pháp hơi tù:
re_export! {
{ pub fn abs(i: c_int) -> c_int }
{ pub fn rand() -> c_int }
{ pub fn foo() }
{ pub fn add(i: c_int, j: c_int) -> c_int }
}
Nguồn
2016-02-24 01:37:00
tôi sẽ giả định bằng tên người dùng của bạn mà bạn đã viết cuốn sách mà bạn đã liên kết. Nó khá tốt! Tôi muốn Google sẽ đề xuất nó cho tôi khi tôi đang nghiên cứu câu hỏi này. – Mastax