Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 为什么我可以返回使用';char.to_ascii_lowercase()`但不与'str.to_lowercase()连用`_Rust_Lifetime_Borrow Checker - Fatal编程技术网

Rust 为什么我可以返回使用';char.to_ascii_lowercase()`但不与'str.to_lowercase()连用`

Rust 为什么我可以返回使用';char.to_ascii_lowercase()`但不与'str.to_lowercase()连用`,rust,lifetime,borrow-checker,Rust,Lifetime,Borrow Checker,在一个接受&str并返回impl Iterator的函数中,我试图将输入转换为小写,然后过滤并映射该小写形式的字符。我在使用str.to_lowercase()时遇到以下错误,已经有一段时间了: 原始形式的功能: pub fn decode_to_iter(cipher: &str) -> impl Iterator<Item = char> { cipher .to_lowercase() .chars() .f

在一个接受
&str
并返回
impl Iterator
的函数中,我试图将输入转换为小写,然后过滤并映射该小写形式的字符。我在使用
str.to_lowercase()
时遇到以下错误,已经有一段时间了:

原始形式的功能:

pub fn decode_to_iter(cipher: &str) -> impl Iterator<Item = char> {
    cipher
        .to_lowercase()
        .chars()
        .filter(|c| c.is_alphanumeric() && c.is_ascii())
        .map(|c| {
            if c.is_alphabetic() {
                (((b'z' - (c as u8)) + b'a') as char)
            } else {
                c
            }
        })
}
最让我困惑的是
str.to_lowercase()
char.to_ascii_lowercase()
之间的区别是什么。下面的
.to_ascii_lowercase()
文档显示:

而下面的
.to_lowercase()
文档显示:

除非我有误解,否则这两个函数似乎都返回一个自有值,所以我不确定为什么只有
char.to\u ascii\u lowercase()
起作用

我想知道:

  • 如何正确返回使用
    .to\u lowercase()
    而不是
    .to\u ascsii\u lowercase()
    Impl迭代器

  • char.to_lowercase()
    str.to_ascii_lowercase()
    之间有什么区别

  • 这里的问题是,分配一个新的
    字符串
    值作为字符串的小写版本,然后该方法借用该新的
    字符串
    值。(通过查看struct,可以看出它借用了
    字符串
    值,struct有一个生命周期参数,该参数引用它正在迭代的字符串。)

    那么,这为什么会有问题呢?嗯,
    分配给_lowercase
    字符串
    值是作为迭代器链的一部分创建的临时值,它反过来会被丢弃在函数作用域的末尾(编译器的错误消息应该告诉您这一点)。因此,编译器阻止您在释放bug后使用。如果它允许您返回迭代器,那么它将允许调用方读取已解除分配的
    字符串
    ,这违反了内存安全

    使用
    char::to_ascii_lowercase
    的变体可以工作,因为您从不分配中间
    String
    值。因此,您将返回一个迭代器,该迭代器从函数的输入中借用,这是有效的,这也是您需要添加生存期参数的原因。(否则,编译器假定
    impl Trait
    的生存期是
    静态的
    ,而这里不是这种情况。返回值的生存期与函数输入的生存期相关联。)

    您可以通过避免分配一个临时的
    字符串来解决这个问题,这应该更有效率。诀窍是认识到
    char
    有一个方法,该方法返回给定字符的小写等价物的迭代器,而不是
    String
    。因此,您可以直接从中阅读:

    pub fn decode_to_iter impl Iterator+'a{
    密码
    .chars()
    .flat_映射(| c | c.to_小写()
    .filter(| c | c.是字母数字()&c.是ascii())
    .map(| c|{
    如果c.是字母(){
    (((b'z'-(c作为u8))+b'a')作为字符)
    }否则{
    C
    }
    })
    }
    
    这里唯一真正的技巧是使用
    flat_map
    ,这类似于普通的
    map
    ,但它允许您返回一个迭代器,然后将其展平为原始迭代器(如果您在这里使用普通的
    map
    ,您将得到一个迭代器迭代器)

    话虽如此,如果您真的只关心这里的ASCII码点(由于您的
    过滤器
    谓词),那么您就不需要完全支持Unicode的小写机制。因此,我可能会将其编写为类似于您的第二个变体,使用
    char::to_ascii_lowercase

      --> src/lib.rs                                                                                                                      
       |                                                                                                                                        
       |        cipher                                                                                                                          
       |   _____^                                                                                                                               
       |  |_____|                                                                                                                               
       | ||                                                                                                                                     
       | ||         .to_lowercase()                                                                                                             
       | ||_______________________- temporary value created here                                                                                
       | |          .chars()                                                                                                                    
       | |          .filter(|c| c.is_alphanumeric() && c.is_ascii())                                                                            
    ...  |                                                                                                                                      
       | |              }                                                                                                                       
       | |          })                                                                                                                          
       | |___________^ returns a value referencing data owned by the current function    
    
    pub fn decode_to_iter impl Iterator+'a{
    密码
    .chars()
    .filter(| c | c.是_ascii_字母数字()
    .map(| c | c.to_ascii_lowercase())
    .map(| c|{
    如果c.是字母(){
    (((b'z'-(c作为u8))+b'a')作为字符)
    }否则{
    C
    }
    })
    }
    

    这是一个显示代码的示例。

    这是因为借用了字符串。您的字符串是否只包含ASCII字符?感谢@BurntSushi5的解释并指出了
    平面地图的使用。关于使用
    char
    小写方法避免不必要的字符串分配,您提出了一个很好的观点,但我仍然想知道是否可以在迭代器链中从
    str::to_lowercase
    获得临时字符串的所有权,以避免将其丢弃在函数作用域的末尾?@AC-5,这将得到回答通过
    pub fn decode_to_iter<'a>(cipher: &'a str) -> impl Iterator<Item = char> + 'a {
        cipher
            .chars()
            .filter(|c| c.is_alphanumeric() && c.is_ascii())
            .map(|c| {
                if c.is_alphabetic() {
                    (((b'z' - (c.to_ascii_lowercase() as u8)) + b'a') as char)
                } else {
                    c.to_ascii_lowercase()
                }
            })
    }
    
    pub fn to_ascii_lowercase(&self) -> char
    
    pub fn to_lowercase(&self) -> String