有没有办法在不重复变量名的情况下将命名参数传递给格式化宏?
Posted
技术标签:
【中文标题】有没有办法在不重复变量名的情况下将命名参数传递给格式化宏?【英文标题】:Is there a way to pass named arguments to format macros without repeating the variable names? 【发布时间】:2018-01-03 13:03:08 【问题描述】:使用新版本的 Rust,您可以像这样简化结构初始化:
Foo
a: a,
b: b,
到这里
Foo a, b
是否可以为format!
/println!
-like 宏做类似的事情?
现在我需要这样写:
let a = "a";
let b = "b";
write!(file, "a is b", a = a, b = b).unwrap();
是否可以使用这样的 API 编写我自己的宏:
let a = "a";
let b = "b";
my_write!(file, "a is b", a, b).unwrap();
【问题讨论】:
我不确定我是否理解您的要求,但您不需要命名格式参数,您可以坚持使用位置参数:write!(file, " is ", a, b)
或 write!(file, "0 is 1", a, b)
。
@E_net4 不,我不需要数字,我想要名字,有〜5个参数,所以我需要它们的名字,比如long_word
,another_long_word
您可能希望阅读std::fmt 上的文档。您编写的代码似乎没有按照您的意愿行事。你能创建一个minimal reproducible example 来显示你当前是如何格式化结构的吗?
我认为使用 variable a
和 string value "a"
可能会使您的示例感到困惑,尤其是文本 @987654335 @。尝试使用具体的东西,例如 name
和 age
。
@E_net4 问题是,格式化程序是否允许 a
在格式化程序中被解释为 a = a
,就像它允许 a
在结构初始化程序中缩写为 a: a
一样。答案是没有 AFAIK?
【参考方案1】:
RFC 2795 已被接受,implemented。从 Rust 1.58 开始,您将能够超越您想要的语法:
write!(file, "a is b").unwrap();
在此之前,您可以围绕println!
和朋友编写自己的包装器:
macro_rules! myprintln
($fmt:expr, $($name:ident),*) => println!($fmt, $($name = $name),*)
fn main()
let a = "alpha";
let b = "beta";
myprintln!("a is b", a, b);
与完整的格式化程序宏相比,这可能总是有限的,但对于您的情况可能就足够了。
【讨论】:
【参考方案2】:截至1.5,这是您可以在本地获得的最接近的。
my_write!(file, " is ", a, b).unwrap();
此外,正如 Shepmaster 指出的那样,我的答案最终会过时(我会尽量记住在发生这种情况时将其删除)。如果您想密切关注他们建议的(待实现的)语法,您可以查看他们链接的this github ticket
【讨论】:
OP 在 2017-07-27 提出了这个问题; Rust 1.18 was the stable release at the time。在问题中,他们已经在使用您建议的语法 (write!(file, "a is b", a = a, b = b).unwrap();
)。具体问题是关于删除a = a
的重复。
我投了赞成票,因为我只是想知道这个答案,谷歌找到了它:)
@Shepmaster 这不是我演示的语法,尽管我愿意进行调整,因为您似乎误解了(我觉得清晰很重要)。如果你看 X 不使用 = 允许更简洁的声明。当然它没有明确的命名(这可以防止重复和乱序分配),但操作没有要求。此外,我明确提到这是针对 1.5(不是 OP 使用的 1.18)。我添加了我的答案,因为这仍然会出现在谷歌搜索中。
但是操作没有要求——他们确实做到了:“有没有办法传递命名参数来格式化宏”。语法
不是命名参数,它是 positional 参数。他们甚至展示了他们想要的示例:my_write!(file, "a is b", a, b)
。
我明确提到这是针对 1.5(不是 OP 使用的 1.18) — 当然,但是为什么呢?您显示的语法自 1.0 以来就存在。为什么随意选择 1.5?以上是关于有没有办法在不重复变量名的情况下将命名参数传递给格式化宏?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不指定每一列的情况下将整行作为参数传递给 Spark(Java)中的 UDF?
有没有办法在 CodeIgniter *不*使用 ActiveRecord 的情况下将参数传递给查询?
在不丢失默认信号参数的情况下将额外参数传递给 PyQt 插槽