impl 没有派生的大型结构的默认糖

Max*_*888 2 syntactic-sugar rust

如果我有一个需要Default实现的结构,如果所有字段的类型都Default实现了它们,那么我可以使用derive宏,否则我需要Default手动实现。但是,在某些情况下,我有一个大型结构,其中几乎所有字段都是可导出的,除了少数字段的类型尚未实现Default,而且我impl自己可以,因为类型是外部的。最终出现以下示例中的情况。我宁愿避免这种情况,因为这意味着我需要保持两个地方之间的字段同步,这更耗时、容易出错且冗长。我希望可能有一些语法方法可以避免这种情况,但我对 rust 很陌生,想不出任何方法。我在想这样的事情:

impl Default for Data2 {
    fn default() -> Self {
        Self {
            external_data: ExternalType::One,
            ..Default::default(),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

例子

#[derive(Default)]
struct Data {
    name: Option<String>,
    flag: bool,
    selected: Vec<String>,
    show_reference: Option<String>,
    index: Option<usize>,
    create_name: String,
    create_type: String,
}

enum ExternalType {
    One,
    Two,
}
// #[derive(Default)]
struct Data2 {
    name: Option<String>,
    flag: bool,
    selected: Vec<String>,
    show_reference: Option<String>,
    index: Option<usize>,
    create_name: String,
    create_type: String,
    external_data: ExternalType,
}
impl Default for Data2 {
    fn default() -> Self {
        Self {
            name: Default::default(),
            flag: Default::default(),
            selected: Default::default(),
            show_reference: Default::default(),
            index: Default::default(),
            create_name: Default::default(),
            create_type: Default::default(),
            external_data: ExternalType::One,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Bal*_*Ben 5

我认为smart-default板条箱可以处理这个问题。它允许您导出SmartDefault,它可以导出Default除具有属性的字段之外的所有字段#[default(my_default_value)]

例子:

use smart_default::SmartDefault;

#[derive(SmartDefault)]
enum Foo {
    Bar,
    #[default]
    Baz {
        #[default = 12]
        a: i32,
        b: i32,
        #[default(Some(Default::default()))]
        c: Option<i32>,
        #[default(_code = "vec![1, 2, 3]")]
        d: Vec<u32>,
        #[default = "four"]
        e: String,
    },
    Qux(i32),
}
Run Code Online (Sandbox Code Playgroud)

还有更通用的板条derivative箱,它可以让您自定义所有派生的工作方式,而不仅仅是Default,但有点更冗长(因为它更通用)。

例子:

use derivative::Derivative;

#[derive(Derivative)]
#[derivative(Default)]
pub struct RegexOptions {
    pub pats: Vec<String>,
    #[derivative(Default(value="10 * (1 << 20)"))]
    pub size_limit: usize,
    #[derivative(Default(value="2 * (1 << 20)"))]
    pub dfa_size_limit: usize,
    pub case_insensitive: bool,
    pub multi_line: bool,
    pub dot_matches_new_line: bool,
    pub swap_greed: bool,
    pub ignore_whitespace: bool,
    #[derivative(Default(value="true"))]
    pub unicode: bool,
}
Run Code Online (Sandbox Code Playgroud)