closures - 在 Rust 中使用标准输入数据实例化结构

标签 closures rust

我对 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_messageget_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>::expectOption<T>::expect方法是您拥有的 match 语句的惯用快捷方式,您希望在其中返回 x如果你得到 Some(x)如果您收到 None,则失败并显示一条消息.

不返回 return
在 Rust 中,在不显式编写 return 的情况下返回值是惯用的(以 Haskell 和 OCaml 等函数式语言为例)。陈述。实际上,函数的返回值是函数中最后一个表达式的结果,除非该表达式后跟一个分号(在这种情况下它返回 () ,也就是单位,它本质上是一个空的占位符值—— () 也是没有明确返回类型的函数返回的内容,例如 mainprint_info )。

结论

无论如何,我都不是 Rust 方面的专家。如果您需要任何有关 Rust 的帮助,除了 Stack Overflow,您还可以尝试 irc.mozilla.org 上的#rust IRC channel 或 Rust subreddit .

关于closures - 在 Rust 中使用标准输入数据实例化结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20861217/

相关文章:

Rust 错误传播在传播级别上具有不同类型

closures - 有什么方法可以装箱和移动关闭吗?

ios - 缺少闭包默认初始值设定项 - 快速闭包变量声明?

JavaScript 闭包 - 使用 ECMA 规范,请解释闭包是如何创建和维护的

closures - 如何编写一个可以组成 `FnMut` 闭包的函数?

rust - 从 HashSet 中删除任何元素并获得所有权(随机顺序很好)

swift - 在 Swift 调用 animateWithDuration :Animations: 中捕获函数参数时出现奇怪的错误

generics - 如果我为 B 实现 From<A>,是否也会为 Vec<B> 实现 From<Vec<A>>?

rust - Cargo 将 git 需求放在哪里?

rust - 在 Rust 中如何从 BigInt 中减 1?