我对 Rust 非常非常陌生,并尝试实现一些简单的东西来感受这门语言。现在,我遇到了实现类结构的最佳方法,该结构涉及将字符串转换为 int。我正在使用一个全局命名空间函数,这对我沉迷于 Ruby 的大脑来说是错误的。
这样做的乡村方式是什么?
use std::io;
struct Person {
name: ~str,
age: int
}
impl Person {
fn new(input_name: ~str) -> Person {
Person {
name: input_name,
age: get_int_from_input(~"Please enter a number for age.")
}
}
fn print_info(&self) {
println(fmt!("%s is %i years old.", self.name, self.age));
}
}
fn get_int_from_input(prompt_message: ~str) -> int {
println(prompt_message);
let my_input = io::stdin().read_line();
let my_val =
match from_str::<int>(my_input) {
Some(number_string) => number_string,
_ => fail!("got to put in a number.")
};
return my_val;
}
fn main() {
let first_person = Person::new(~"Ohai");
first_person.print_info();
}
这编译并具有所需的行为,但我不知道在这里做什么 - 很明显我不了解最佳实践或如何实现它们。
编辑:这是 0.8
最佳答案
这是我的代码版本,我做得更惯用了:
use std::io;
struct Person {
name: ~str,
age: int
}
impl Person {
fn print_info(&self) {
println!("{} is {} years old.", self.name, self.age);
}
}
fn get_int_from_input(prompt_message: &str) -> int {
println(prompt_message);
let my_input = io::stdin().read_line();
from_str::<int>(my_input).expect("got to put in a number.")
}
fn main() {
let first_person = Person {
name: ~"Ohai",
age: get_int_from_input("Please enter a number for age.")
};
first_person.print_info();
}
fmt!
/format!
首先,Rust 正在弃用
fmt!
宏,带有 printf
- 基于语法,支持 format!
, 它使用类似于 Python format strings 的语法.新版本 Rust 0.9 会提示使用 fmt!
.因此,您应该替换 fmt!("%s is %i years old.", self.name, self.age)
与 format!("{} is {} years old.", self.name, self.age)
.但是,我们有一个方便的宏 println!(...)
这意味着与 println(format!(...))
完全相同的东西, 所以用 Rust 编写代码最惯用的方法是println!("{} is {} years old.", self.name, self.age);
初始化结构
对于像
Person
这样的简单类型,在 Rust 中,使用 struct 字面量语法创建类型的实例是惯用的:let first_person = Person {
name: ~"Ohai",
age: get_int_from_input("Please enter a number for age.")
};
如果您确实需要构造函数,
Person::new
是类型 Person
的“默认”构造函数(我的意思是最常用的构造函数)的惯用名称。 .但是,默认构造函数要求用户输入进行初始化似乎很奇怪。通常,我认为您会有 person
模块,例如(带有 person::Person
由模块导出)。在这种情况下,我认为使用模块级函数 fn person::prompt_for_age(name: ~str) -> person::Person
是最惯用的。 .或者,您可以在 Person
上使用静态方法-- Person::prompt_for_age(name: ~str)
.&str
与 ~str
在函数参数中我已更改
get_int_from_input
的签名采取&str
而不是 ~str
. ~str
表示在交换堆上分配的字符串——换句话说,malloc
的堆/free
在 C 中,或 new
/delete
在 C++ 上进行操作。然而,与 C/C++ 不同的是,Rust 强制要求交换堆上的值一次只能由一个变量拥有。因此,采取~str
作为函数参数意味着函数的调用者不能重用 ~str
它传入的参数——它必须复制 ~str
使用 .clone
方法。另一方面,
&str
是字符串中的一个切片,它只是对字符串中一系列字符的引用,因此当函数使用 &str
时,不需要分配字符串的新副本。参数被调用。使用原因
&str
而不是 ~str
对于 prompt_message
在 get_int_from_input
是函数不需要在函数结束后保留消息。它仅使用提示消息来打印它( println
采用 &str
,而不是 ~str
)。一旦您将函数更改为 &str
, 你可以这样称呼它 get_int_from_input("Prompt")
而不是 get_int_from_input(~"Prompt")
,从而避免了 "Prompt"
的不必要分配在堆上(同样,您可以避免在下面的代码中克隆 s
):let s: ~str = ~"Prompt";
let i = get_int_from_input(s.clone());
println(s); // Would complain that `s` is no longer valid without cloning it above
// if `get_int_from_input` takes `~str`, but not if it takes `&str`.
Option<T>::expect
Option<T>::expect
方法是您拥有的 match 语句的惯用快捷方式,您希望在其中返回 x
如果你得到 Some(x)
如果您收到 None
,则失败并显示一条消息.不返回
return
在 Rust 中,在不显式编写
return
的情况下返回值是惯用的(以 Haskell 和 OCaml 等函数式语言为例)。陈述。实际上,函数的返回值是函数中最后一个表达式的结果,除非该表达式后跟一个分号(在这种情况下它返回 ()
,也就是单位,它本质上是一个空的占位符值—— ()
也是没有明确返回类型的函数返回的内容,例如 main
或 print_info
)。结论
无论如何,我都不是 Rust 方面的专家。如果您需要任何有关 Rust 的帮助,除了 Stack Overflow,您还可以尝试 irc.mozilla.org 上的#rust IRC channel 或 Rust subreddit .
关于closures - 在 Rust 中使用标准输入数据实例化结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20861217/