rust 有可能不使用寿命参数来编写这个程序吗?

wfsdck30  于 2023-06-23  发布在  其他
关注(0)|答案(3)|浏览(71)

有没有可能在不使用lifetime参数的情况下编写这个程序

pub fn anagrams_for<'a>(word: &'a str, 
        possible_anagrams: &'a [&'a str]) -> Vec<&'a str>

main.rs

pub fn is_anagram(one_word: &str, other_word: &str) -> bool {
    if one_word.len() != other_word.len() {
        return false;
    }
    for ch in one_word.chars() {
        if other_word.find(ch) == None {
            return false;
        }
    }
    true
}

pub fn anagrams_for<'a>(word: &'a str, possible_anagrams: &'a [&'a str]) -> Vec<&'a str> {
    let mut return_list = Vec::new();
    for &item_str in possible_anagrams.iter() {
        if is_anagram(word, item_str) {
            return_list.push(item_str);
        }
    }
    return_list
}

fn main() {
    let word = "inlets";
    let inputs = ["hello", "world", "listen", "pants"];
    println!("{:?}", anagrams_for(word, &inputs));
}
wsewodh2

wsewodh21#

根据生存期省略规则,这是不可能的:
输入位置中的每个省略的寿命变成不同的寿命参数。这是fn定义的当前行为。
(* 为了理解您可能想要检查终身职位 *)
根据规则,函数的定义将有3个不同的生命周期参数。

pub fn anagrams_for(word: &str, possible_anagrams: &[&str]) -> Vec<&str>

有3个不同的生命周期参数是可以的,但是Rust不能选择哪个参数应该用于输出位置-> Vec<&str>
来自输入位置的一个生存期(或 * 较小 *)需要用于输出位置(当然它应该是与返回值相关的生存期),除非你不返回'static生存期,尽管你应该显式声明为Vec<&'static str>(这个主题与所有权和借用,悬空指针有关)

**注意:**通过 * 更小 *,我的意思是从输入位置选择的生存期所包含的生存期。

还有一条规则你可能要检查一下
如果有多个输入生存期位置,但其中一个是&self或&mut self,则self的生存期将分配给所有省略的输出生存期。
这意味着像这样的代码将适用于生存期省略,但您只能从&self返回一些内容,而不能从其他内容返回。

struct SomeStruct;
impl SomeStruct {
    pub fn anagrams_for(&self, word: &str, possible_anagrams: &[&str]) -> Vec<&str> { 
        //...
        //return value(s) should be related with `&self`
    }
}
olmpazwi

olmpazwi2#

可以这么说。所写的程序可以使用'static生存期。

pub fn anagrams_for(word: &str, possible_anagrams: &[&'static str]) -> Vec<&'static str> {

然而,这是过度限制。正确的书写方式是这样的。

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> Vec<&'a str> {

这个函数总是可以用来代替第一个函数。
重要的是要理解函数签名中的每个引用总是有一个生存期。大多数情况下,这些都是推断出来的,但总是有一个等价的函数为每个引用分配生命期。上一个函数与此相同。

pub fn anagrams_for<'a, 'b, 'c>(word: &'b str, possible_anagrams: &'c [&'a str]) -> Vec<&'a str> {
h4cxqtbf

h4cxqtbf3#

答案

您确实需要包括lifetime参数,因为在这里不能进行生存期省略。编译器生成的错误包括原因,即Rust无法判断返回值是从word还是possible_anagrams借用的。

隐藏问题

虽然您添加生存期的方式确实可以满足编译器的要求,但可能会产生意想不到的副作用。考虑:

let inputs = ["hello", "world", "listen", "pants"];
let matches = {
    // Pretend this was getting user input.
    let word = String::from("inlets");
    anagrams_for(&word, &inputs)
};
println!("{matches:?}");

这将无法编译,因为根据函数签名,anagrams_for的返回值借用了word,而word的生存时间不够长。不过,这并不重要,因为我们知道我们不是从文字中借用。因此,让我们更新函数签名以使其工作:

pub fn anagrams_for<'a>(word: &str, possible_anagrams: &[&'a str]) -> Vec<&'a str> {
    let mut return_list = Vec::new();
    for &item_str in possible_anagrams.iter() {
        if is_anagram(word, item_str) {
            return_list.push(item_str);
        }
    }
    return_list
}

这里返回值的生存期与possible_anagrams中的&str相同,这意味着它不再绑定到测试字的生存期。

无关说明:

anagrams_for的主体也可以写为:

possible_anagrams
    .iter()
    .map(|ana| *ana)
    .filter(|ana| is_anagram(word, ana))
    .collect()

相关问题