从一开始就有Rust,功能

80 阅读5分钟

在Rust从头开始系列的这一部分,我们将看看函数,以及它们如何帮助我们创建可重用的部分代码。

资源

函数是什么,为什么我需要它们?

一个函数是一个命名的引用,至少包含一个,通常是许多语句。函数的一些好处是。

  • 可重用性和清理性。当你创建一个函数时,你经常这样做,因为你发现有一些代码是重复的。通过创建一个函数,你可以在其他地方使用它,用重复的模式来代替它。想象一下,在你的代码中发生了如下情况。
   let mut account_balance = 100.20;
   let stock_sales = 50;
   let mut actual_deposit = 50 * 0.51;
   account_balance += actual_deposit;
   // some other lines of code
   let stock_sales = 100;
   actual_deposit = 100 * 0.51;
   account_balance += actual_deposit;

在这里你看到,卖出股票首先是卖出它,其次是给税务局一定的百分比。最后,将收益用于账户余额。这是一个在代码中重复的行为,尽管数值略有不同。

通过创建一个函数get_stock_procceed() ,可以实现上述代码的一个简单版本,它也隐藏了一些行为。

   let mut account_balance = 100.20;
   account_balance = get_stock_proceed(50);
   // some other lines of code
   account_balance = get_stock_proceed(100);
  • 可读性。添加一个函数将实现的另一个目的是可读性,一个函数是以它所做的事情来命名的,加法或乘法的东西不像说 "获得某物的收益 "那样有表现力。另外,行数越少,越容易阅读,(在一定程度上)。

第一个函数

那么,我们希望对函数的内容和原因有更多的了解,我们如何创建它们呢?我们使用fn 关键字、函数的名称、小括号和大括号来创建一个函数。

这里有一个例子。

fn say_hi() {
  println!("Hi");
}

为了调用它,你用名字来指代它,并加上开放和关闭的小括号。

say_hi();

返回一个值

上面的say_hi() 函数并不返回任何东西。通常,你希望一个函数有这种能力。原因是你想让函数进行某种计算,如两个数字相加,或者乘积也许是一个随机数字。

有两种方法来返回一个值。

  • 使用return 关键字。这个想法是,你向函数发出信号,在这一点上你已经准备好返回值,并退出函数,像这样。
   fn get_message(temperature_in_celsius:i32) -> &'static str {
      if temperature_in_celsius < 0 {
        return "Freezing";
      } 
      return "Ok temp";
   }

在这段代码中,代码有两种不同的执行路径,这取决于我向函数提供什么值,在这一点上,我需要一个return 语句来明确地说,这就是我需要退出函数的地方。

  • 最后一行。从函数中返回一个值的另一种方法是,像这样把你想要的东西放在函数的最后一行。
   fn produce_number() -> i32 {
     let number = 3;
     let another_number = 5;
     number + another_number;
   }

函数的最后一行是返回的内容,要接收返回的值,请调用函数并像这样分配。

   let value = produce_number();
   println!("{}", value);

或直接使用该值,像这样。

   println!("{}", produce_number());

到目前为止你已经看到了一些东西,一个箭头-> ,就在函数的括号后面,那是什么?那是函数的返回类型。如果函数返回什么,就需要它。对于produce_number() ,函数的返回类型是i32 ,我们这样写。-> i32.对于下面的divide() 函数,我们把返回类型定为f32 ,因为我们的意思是要处理小数问题。

fn divide() -> f32 {
  5 as f32 / 2 as f32
}

那么,这里发生了什么,f32 ,但也有as f32 ?让我们回过头来,从这个函数的一个更简单的版本开始。

fn divide2() -> i32 {
  5 / 2
}

如果你运行这个函数,你会得到2的响应,这可能不是你想要的。然而,由于你将返回类型设为i32 ,你得到的是一个整数,并且去掉了小数。那我们就把它改成小数吧。

fn divide() -> f32 {
  5 / 2
}

在这一点上,你得到一个编译错误。

  --> app.rs:21:3
   |
20 | fn divide() -> f32 {
   |                 --- expected `f32` because of return type
21 |   5 / 2
   |   ^^^^^ expected `f32`, found integer

它指出5和to是整数,我们需要改变它。我们要么把它们写成5.0和2.0,要么使用运算符as ,把它们变成浮点数。我们选择了后者,5 as f32 ,这就是我们得到的结果。这是一个非常静态的函数,我们不能用它做很多事情,如果我们能把任何数值传给它,让它为我们做计算,那就更好了,为此我们需要参数。

添加参数

参数是我们送入一个函数的东西。要向一个函数发送一些东西,我们需要一个占位符,一个可以捕捉我们传入的值的参数,像这样。

fn divide(placeholder:f32, second_placeholder: f32) {
  placeholder / second_placeholder;
}

现在我们已经删除了5和2,增加了参数placeholdersecond_placeholder 。当我们现在调用这个函数时,我们可以向它发送数值。

println!("{}", divide(5,2)); // 2.5
println!("{}", divide(10,2)); // 5

练习--建立一个计算器

在这个练习中,你将建立一个可以处理加、减、乘、除的计算器。

  1. 创建一个main.rs文件并添加以下代码。
   fn add(first_number: i32, second_number: i32) -> i32 {
     first_number + second_number
   }

   fn main() {
     let sum = add(2,2);
     let quotient = divide(10 as f32, 2 as f32);
     let product = multiply(2, 5);
     println!("{}", sum); // 8
   }

你能加上所缺的东西吗?给它一些时间,试着实现divide()multiply() 。完整的解决方案可以在下一节找到。

完整的解决方案 - 计算器

fn add(first_number: i32, second_number: i32) -> i32 {
  first_number + second_number
}

fn divide(first_number: f32, second_number: f32) -> f32 {
  first_number / second_number
}

fn multiply(first_number: i32, second_number: i32) -> i32 {
  first_number * second_number;
}

fn main() {
  let sum = add(2,2);
  let quotient = divide(10 as f32, 2 as f32);
  let product = multiply(2, 5);
  println!("{}", sum);
  println!("{:.2}", quotient);
  println!("{}", product);
}

额外奖励

看看你是否也能实现一个subtract()

小结

在本教程中,你了解了函数,为什么会有这些函数,以及如何自己创建函数。希望你感到有能力创建自己的函数。