dpo*_*key -2 fizzbuzz rust lifetime-scoping
这是我的代码:
fn main() {
fn fizz_buzz<'a>(i: i32) -> &'a str {
if i % 15 == 0 {
"FizzBuzz"
} else if i % 5 == 0 {
"Buzz"
} else if i % 3 == 0 {
"Fizz"
} else {
&i.to_string()
}
}
for i in 1..101 {
println!("{}" , fizz_buzz(i));
}
}
Run Code Online (Sandbox Code Playgroud)
编译器给我这个错误:
error[E0515]: cannot return reference to temporary value
--> src/main.rs:11:9
|
11 | &i.to_string()
| ^-------------
| ||
| |temporary value created here
| returns a reference to data owned by the current function
For more information about this error, try `rustc --explain E0515`.
error: could not compile `playground` due to previous error
Run Code Online (Sandbox Code Playgroud)
我尝试过静态生命周期。
您的函数将正确返回对字符串“FizzBuzz”、“Buzz”和“Fizz”的引用(它们的生命周期是静态的,因为它们被编译进去),但是它们&i.to_string()不具有相同的属性。让我们详细看看生命周期:
当fizz_buzz被调用时,i被复制(因为 i32 实现了 Copy 特征)并给予它。然而,在 else 块中,我们执行以下操作:
StringString然而,它的生命周期String只有 fizz_buzz 函数调用那么长!由于我们需要在该范围之外使用它的引用,Rust 称之为“犯规”。
有几种方法可以使这种类型安全。您可以返回拥有的值而不是引用:
fn fizz_buzz(i: i32) -> String {
if i % 15 == 0 { String::from("FizzBuzz") }
else if i % 5 == 0 { String::from("Buzz") }
else if i % 3 == 0 { String::from("Fizz") }
else { i.to_string() }
}
Run Code Online (Sandbox Code Playgroud)
尽管这最终会在堆上创建许多相同的对象(例如,考虑有多少“Fizz”)
我更喜欢的另一个选项是让 fizz_buzz 返回 Option<&str>,并让调用范围处理 fizz_buzz 给出 None 时的情况。
fn fizz_buzz(i: i32) -> Option<&'static str> {
if i % 15 == 0 { Some("FizzBuzz") }
else if i % 5 == 0 { Some("Buzz") }
else if i % 3 == 0 { Some("Fizz") }
else { None }
}
for i in 1..101 {
match fizz_buzz(i) {
Some(v) => println!("{}", v),
None => println!("{}", i),
}
}
Run Code Online (Sandbox Code Playgroud)
正如@RobinZigmond 在评论中指出的那样,您还可以返回一个枚举并为其实现 Display。
use std::fmt::{self, Display};
enum FizzBuzz {
FizzBuzz,
Fizz,
Buzz,
Other(i32)
}
impl Display for FizzBuzz {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::FizzBuzz => write!(f, "{}", "FizzBuzz"),
Self::Fizz => write!(f, "{}", "Fizz"),
Self::Buzz => write!(f, "{}", "Buzz"),
Self::Other(i) => write!(f, "{}", i.to_string())
}
}
}
fn fizz_buzz(i: i32) -> FizzBuzz {
if i % 15 == 0 { FizzBuzz::FizzBuzz }
else if i % 5 == 0 { FizzBuzz::Buzz }
else if i % 3 == 0 { FizzBuzz::Fizz }
else { FizzBuzz::Other(i) }
}
fn main() {
for i in 1..101 {
println!("{}", fizz_buzz(i));
}
}
Run Code Online (Sandbox Code Playgroud)