目前,将扩展方法添加到另一个模块中的类型(即使此模块位于子模块中)的唯一方法是定义新特征并为该类型实现它。然而,这非常笨拙,因为方法的数量变得很大:
trait Ops {
fn parse_list_item(&self, current_item: ListItemInfo)
-> ParseResult<(Document, ListItemInfo)>;
fn parse_list_item_content(&self) -> ParseResult<Document>;
}
impl<'a> Ops for MarkdownParser<'a> {
fn parse_list_item(&self, current_item: ListItemInfo)
-> ParseResult<(Document, ListItemInfo)> {
// ...
}
fn parse_list_item_content(&self) -> ParseResult<Document> {
// ...
}
}
您必须两次编写方法签名。如果更改,您还必须在多个位置更新它。它还会增加很多噪音。
我虽然这些宏会有所帮助,但我不知道如何为函数中的参数列表编写正确的macro_rules!
模式。以下是我到目前为止的情况:
#![feature(macro_rules)]
struct Foo;
macro_rules! ops (
($(fn $name:ident($($args:tt)*) -> $ret:ty $body:block)+) => (
trait Ops {
$(fn $name($($args)*) -> $ret;)+
}
impl Ops for Foo {
$(fn $name($($args)*) -> $ret $body)+
}
)
)
mod ops {
ops! {
fn method1(&self) -> int {
10
}
fn method2(&self, i: int) -> () {
println!("{}", i + self.method1());
}
}
pub fn run_test() {
Foo.method2(22);
}
}
fn main() {
ops::run_test();
}
它以相当令人讨厌的信息失败了:
/tmp/rs/ops/src/main.rs:8:27: 8:31 error: expected type, found token INTERPOLATED(NtTT(ptr::P<ast::TokenTree>{ptr: box TTTok(codemap::Span{lo: codemap::BytePos(337u32), hi: codemap::BytePos(338u32), expn_id: codemap::ExpnId(4294967295u32)}, BINOP(AND))}))
/tmp/rs/ops/src/main.rs:8 $(fn $name($($args)*) -> $ret;)+
^~~~
它可能值得一个bug报告,因为错误信息非常令人生畏,但是,我没有看到另一种传递参数的方法。它似乎与this issue有关,但是,我希望有一种解决方法 in this case
有什么建议吗?