创建具有静态生命周期的匿名变量时的最佳做法是什么?
What are best practices when creating an anonymous variable with static lifetime?
这是一个由两部分组成的问题:(1) 传递高阶函数静态引用以使它们(参数)足够长的时间是否是一种好习惯? (2) 创建具有静态生命周期的匿名变量的最佳方法是什么?
这是上下文:我有一个元函数,returns 一个基于其参数的闭包。为了确保参数的寿命足够长,它们必须是静态引用。例如,
pub enum Uncloneable { Variant }
pub fn get_getter(param:&'static Uncloneable)
-> Box<dyn Fn() -> &'static Uncloneable> {
Box::new(move || { param })
}
但我不想每次调用 get_getter
时都用大量 const
定义来弄乱我的代码,例如
fn main() {
let _result = get_getter({
const VAR:Uncloneable = Uncloneable::Variant;
&VAR
});
}
我目前的解决方案是使用宏:
#[macro_export]
macro_rules! staticify {
($type:tt :: $variant:tt) => {{
const VAR:$type = $type::$variant;
&VAR
}};
}
fn main() {
let _result = get_getter(staticify!(Uncloneable::Variant));
}
效果很好,但我担心我可能会在这里重新发明轮子(甚至犯下一些反模式)。
我不认为你的宏是反模式,但在这种情况下它不一定很有用。 const
不为该值分配任何存储空间,它只是在编译时进行替换,因此您的代码与以下内容相同:
fn main() {
let _result = get_getter(&Uncloneable::Variant);
}
换句话说,用const
来存储值没有必要也没有什么不同。
此外,引用自动升级为 &'static Uncloneable
。 Rust reference explains:
When using a value expression in most place expression contexts, a temporary unnamed memory location is created initialized to that value and the expression evaluates to that location instead, except if promoted to 'static
. Promotion of a value expression to a 'static
slot occurs when the expression could be written in a constant, borrowed, and dereferencing that borrow where the expression was originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain interior mutability or destructors (these properties are determined based on the value where possible, e.g. &None
always has the type &'static Option<_>
, as it contains nothing disallowed).
所以本质上,如果你可以像你的代码一样使用常量,你也可以直接引用该值,如果可以的话,它会自动提升为 'static
引用。
这是一个由两部分组成的问题:(1) 传递高阶函数静态引用以使它们(参数)足够长的时间是否是一种好习惯? (2) 创建具有静态生命周期的匿名变量的最佳方法是什么?
这是上下文:我有一个元函数,returns 一个基于其参数的闭包。为了确保参数的寿命足够长,它们必须是静态引用。例如,
pub enum Uncloneable { Variant }
pub fn get_getter(param:&'static Uncloneable)
-> Box<dyn Fn() -> &'static Uncloneable> {
Box::new(move || { param })
}
但我不想每次调用 get_getter
时都用大量 const
定义来弄乱我的代码,例如
fn main() {
let _result = get_getter({
const VAR:Uncloneable = Uncloneable::Variant;
&VAR
});
}
我目前的解决方案是使用宏:
#[macro_export]
macro_rules! staticify {
($type:tt :: $variant:tt) => {{
const VAR:$type = $type::$variant;
&VAR
}};
}
fn main() {
let _result = get_getter(staticify!(Uncloneable::Variant));
}
效果很好,但我担心我可能会在这里重新发明轮子(甚至犯下一些反模式)。
我不认为你的宏是反模式,但在这种情况下它不一定很有用。 const
不为该值分配任何存储空间,它只是在编译时进行替换,因此您的代码与以下内容相同:
fn main() {
let _result = get_getter(&Uncloneable::Variant);
}
换句话说,用const
来存储值没有必要也没有什么不同。
此外,引用自动升级为 &'static Uncloneable
。 Rust reference explains:
When using a value expression in most place expression contexts, a temporary unnamed memory location is created initialized to that value and the expression evaluates to that location instead, except if promoted to
'static
. Promotion of a value expression to a'static
slot occurs when the expression could be written in a constant, borrowed, and dereferencing that borrow where the expression was originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain interior mutability or destructors (these properties are determined based on the value where possible, e.g.&None
always has the type&'static Option<_>
, as it contains nothing disallowed).
所以本质上,如果你可以像你的代码一样使用常量,你也可以直接引用该值,如果可以的话,它会自动提升为 'static
引用。