我目前正在尝试用 Rust 编写一个小的命令行应用程序,但我在生命周期方面遇到了瓶颈。
extern crate clap;
use self::clap::{App, Arg};
use std::env;
impl<'p> Params<'p> {
fn get_username_arg<'r>() -> Arg<'r, 'r> {
let mut arg = Arg::with_name("Username")
.short("u")
.long("username")
.takes_value(true);
match env::var("USERNAME") {
Ok(username) => {
// How do I pass `username` to default_value?
arg.default_value(username)
}
Err(e) => arg.required(true),
}
}
// More code below...
}
问题是我试图将 username
传递给默认值方法,这需要 str
的生命周期为 'r
。我试过克隆,但我不知道如何告诉它克隆的生命周期是多少。我尝试了以下几行:
let cln = (&*username).clone::<'r>();
arg.default_value(username)
出于某种原因,它现在告诉我 username
的生命周期不够长,尽管自从我克隆了数据后这应该无关紧要。
所以我的问题是,我该如何进行编译?
编辑:我想补充一点,除了生命周期参数之外,签名保持不变对我来说很重要。我不介意进行昂贵的操作(例如克隆)来完成这项工作。
最佳答案
malbarbo has provided some good solutions ,但我想讨论非工作代码的某些方面。
让我们从函数签名开始:
fn get_username_arg<'r>() -> Arg<'r, 'r> {
这表示“对于此函数的调用者选择的任何生命周期,我将返回一个Arg
,其中包含将持续那么长时间的引用”。这是一个很难坚持的 promise ,因为调用者可能会请求满足 'static
的东西。生命周期,一个比调用 main
持续更长的值!事实上,您可以履行“任何一生”义务的唯一方法是返回 'static
的东西。 .
这是一个非常好的迹象,表明将会出现问题。另见 Why can't I store a value and a reference to that value in the same struct? ,它将这种情况显示为构造函数。许多人跳到试图返回 String
连同 &str
,因此该答案也可能使该途径短路。 ^_^
username
doesn't live long enough, even though it shouldn't matter since I cloned the data.
username
有一个非常具体的生命周期,而且是有限的。如果您查看一段代码,通常可以直接找出对象的生命周期:它是变量在不移动的情况下所在的 block 的范围。在您的示例中,username
只存在于作为匹配臂的一部分的 block 中 Ok(username) => { // }
.一旦该 block 退出,该值就会被销毁。
clone
in this case has a signature of<'s>clone() -> &'s str
if you remove elisions (and reifySelf
) according to my very limited understanding of Rust in general.
env::var
返回 Result<String, VarError>
,然后您访问 Ok
变体,制作username
一个String
. String
implementation of clone
需要 &String
并返回 String
.我不确定 -> &'s str
在哪里会来自。
So if I clone with
clone::<'r>()
it should force the lifetime...
这是一个非常的常见错误。查看Do Rust lifetimes influence the semantics of the compiled program? (可能还有 Why are explicit lifetimes needed in Rust? )以获取一些背景信息。您不能更改某物的生命周期,除非重写您的代码以使引用的值具有更大的范围。生命周期语法反射(reflect)了变量的生命周期,它不控制它。没有(安全的)方法可以“强制”一生。
(&*username).clone
has that signature I mean
如果我们取消引用并重新引用 String
,我们最终得到一个 &str
.那&str
将有一个对应于 String
多长时间的生命周期生活。这是有道理的,因为 &str
只是指向 String
.当 String
被释放,&str
将指向不再处于有效状态的内存。
关于rust - 将字符串克隆到特定的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37502627/