首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rust宏的关键字参数

Rust宏的关键字参数
EN

Stack Overflow用户
提问于 2021-04-26 00:29:16
回答 3查看 136关注 0票数 1

假设我有一个这样的结构:

代码语言:javascript
复制
struct Foo {
  a: i32,
  b: i32,
}

有没有可能用macro_rules定义一个宏,这样我就可以创建这样的Foo了?

代码语言:javascript
复制
let f1 = make_foo!(
  a=5,
);
let f2 = make_foo!(
  b=2,
  a=6,
);
let f3 = make_foo!(
  b=9,
);
let f4 = make_foo!();

我希望所有参数都是可选的-我将在宏中或通过Default特性指定一个默认值-理想情况下,顺序并不重要,尽管这只是“拥有它很好”。

EN

回答 3

Stack Overflow用户

发布于 2021-04-26 01:11:57

使用字段记录更新语法可以做到这一点:

代码语言:javascript
复制
#[derive(Debug, Default)]
struct Foo {
    a: i32,
    b: i32,
}

macro_rules! make_foo {
    ($($field:ident = $value:expr),* $(,)?) => {
        Foo {
            $(
                $field: $value,
            )*
            ..Default::default()
        }
    }
}

Playground

票数 2
EN

Stack Overflow用户

发布于 2021-04-26 03:40:00

为了跟进Cerberus的回答,如果您想对传递的值进行逐个字段处理,可以添加一个具有匹配字段名的函数的模块,如下所示:

代码语言:javascript
复制
#[derive(Debug, Default)]
pub struct Foo {
    a: i32,
    b: String,
}

mod foo_setters {
    pub fn a(x: i32) -> i32 { x }
    pub fn b(x: &str) -> String { x.to_owned() }
}

macro_rules! make_foo {
    ($($field:ident = $value:expr),* $(,)?) => {
        Foo {
            $(
                $field: foo_setters::$field($value),
            )*
            ..Default::default()
        }
    }
}

pub fn foo() -> Foo {
    make_foo!(
        a = 5,
        b = "hi", // No need for .to_string()!
    )
}
票数 1
EN

Stack Overflow用户

发布于 2021-04-26 00:42:09

棘手的部分是找出存在哪些字段。也许可以编写一个proc宏来实现这一点,但我建议您使用另一种方法。

Rust中惯用的方式是使用Builder模式。有一个crate可以自动为您的:https://docs.rs/derive_builder/0.10.2/derive_builder/编写这些构建器

这个也存在:https://crates.io/crates/typed-builder

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67255730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档