在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,增加了参数placeholder 和second_placeholder 。当我们现在调用这个函数时,我们可以向它发送数值。
println!("{}", divide(5,2)); // 2.5
println!("{}", divide(10,2)); // 5
练习--建立一个计算器
在这个练习中,你将建立一个可以处理加、减、乘、除的计算器。
- 创建一个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() 。
小结
在本教程中,你了解了函数,为什么会有这些函数,以及如何自己创建函数。希望你感到有能力创建自己的函数。