2个不稳定版本
使用旧的Rust 2015
0.2.0 | 2018年6月26日 |
---|---|
0.1.0 | 2018年6月24日 |
#1065 in 过程宏
1MB
122 行
Prismatic
一个用于分解结构体初始化的实验性Rust包。
概述
Rust中一个常见的惯用方法是定义一个new
函数来初始化结构体。有时这个函数可以相当大。如果您尝试将其分解为步骤,您通常会留下复杂的私有函数签名。
impl Webpage {
pub fn new(title: &str) -> Self {
let window = Self::fetch_window();
let document = Self::fetch_document();
let body = Self::fetch_body(&document);
let canvas = Self::create_canvas(&document);
let context = Self::fetch_context(&canvas);
Self::set_page_title(&document, title);
Self::reset_styles(&document, &body);
Self::add_canvas_to_page(&body, &canvas);
Self::resize_canvas(&body, &canvas);
Self::bind_resize_event(&window, &body, &canvas);
Webpage { window, document, body, canvas, context }
}
fn fetch_body(document: &Document) -> Body {
document.body().expect("failed to fetch body")
}
fn bind_resize_event(window: &Window, body: &Body, canvas: &canvas) {
// ...
}
// ...
}
Prismatic
Prismatic提供了一个宏,使这变得容易一些。它生成一个特殊的Init
结构体,可以用于初始化,减少了提取每个步骤函数的开销。
#[macro_use]
extern crate prismatic;
#[derive(New)]
#[Sig = "title: &str"]
struct Webpage {
window: Window,
document: Document,
body: Body,
canvas: Canvas,
context: Context,
}
impl Init {
fn init(&mut self, title: &str) {
self.fetch_window();
self.fetch_document();
self.fetch_body();
self.create_canvas();
self.fetch_context();
self.set_page_title(title);
self.reset_styles();
self.add_canvas_to_page();
self.resize_canvas();
self.bind_resize_event();
}
fn fetch_body(&mut self) {
let body = self.document().body().expect("failed to fetch body");
self.set_body(body);
}
fn bind_resize_event(&self) {
// ...
}
// ...
}
在上面的示例中,fetch_body
函数使用document()
getter方法和set_body()
setter方法设置body。在初始化期间,为结构体中的所有字段自动生成getter和setter。
使用方法
这里有一个最小示例
#[macro_use]
extern crate prismatic;
#[derive(New)]
struct Foo { bar: usize }
impl Init {
fn init(&mut self) {
self.set_bar(123);
}
}
let foo = Foo::new()
assert_eq!(foo.bar, 123);
如果初始化器需要额外的参数,可以使用Sig
属性(即Signature
)
#[derive(New)]
#[Sig = "x: usize"]
struct Foo { bar: usize }
impl Init {
fn init(&mut self, x: usize) {
self.set_bar(x);
}
}
let foo = Foo::new(123);
assert_eq!(foo.bar, 123);