那麽最一开始学一个程序语言的起手式想必不用我多说吧。
「Hello World!」
fn hello() {
println!("Hello World!");
}
那你可能想说,为什麽不是 main function
因为我 source code 放在 Github 上阿。
我打算把它区分清楚这样查阅的时候也比较方便 owo 。
Github连结
希望有人帮我按星星 owo/
那接下来就是基本的介绍。
Rust 的函数写法就是
fn function_name(/*引入*/){
//code
}
那中间就是撰写 code 的主要位置。
但是如果说是稍微有程序观念的就会知道我少讲了一个东西。
「回传值格式」
在 Rust 里回传值的设定方法就是
fn function_name(/*引入*/) -> /*回传值形式*/{
/*code*/
}
回传方式有两种
2.可能看起来比较复杂,直接看 code 吧
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// 回传 a + b
pub fn add(a: i32, b: i32) -> i32 {
a + b
a += b;
}
// 不合法
pub fn add(a: i32, b: i32) -> i32 {
return a + b;
a += b;
}
// 但是可以这样写
要注意的是函数也可以作为引数传入函数中,有点绕口令,还是看 Code 啦
fn into(op: fn(i8, i8) -> i8, a: i8, b: i8) -> i8 {
op(a, b)
}
fn add(a: i8, b: i8) -> i8 {
a + b
}
fn product(a: i8, b: i8) -> i8 {
a * b
}
pub fn oao() {
let a = 5;
let b = 4;
println!("{}", into(add, a, b));
println!("{}", into(product, a, b));
}
那可能有些人,会特别在意速度,那其实 Rust 也有 CTFE (Compile Time Function Evaluation)
也就是编译期处理,把原本要运行的东西拉入编译中处理。
我自己是在学 Rust 前不知道这个东西,所以不确定其他语言有没有
写法如下
pub const fn CTFE() -> i8 {
5
}
就前面加一个 const 即可,我自己测试 Stable 版本中已经可用了
pub fn owo(){
println!("1");
}
pub fn func() {
owo();
{
owo();
fn owo(){
println!("2");
}
}
}
具体输出为
那可以发现说 他的函数会先吃同样的范围的。
而不会吃外面的,但是我也不会这样写。
可读性有够差 感觉混淆程序码很好用
在 Rust 中可以一次回传多项。
就像是
pub fn retmany() -> (i32, i32) {
(5, 8)
}
这样的话其实他的回传值就有两个,但是相对的,也要靠两个变数去接
就像是这样
pub fn return_many() {
let (a, b) = function::retmany();
println!("{} {}", a, b);
}
就能接到 a 跟 b 两个值
如果这样写
pub fn uninput(_: i32) {
println!("{}", _);
}
并使用,会报错
error: in expressions, `_` can only be used on the left-hand side of an assignment
--> src/Basic/function.rs:21:20
|
21 | println!("{}", _);
| ^ `_` not allowed here
也就是可以让传入的东西不能用,应该在後面的 Bevy Engine 会用到。
先解释一下泛型函数的使用用途。
今天如果说,要写一个能使用多型别 Ex: float, Int 的程序,
那可能你就要重复写两个函数,差别只有一个是 Float 型式的一个是 Int 型式的
为了解决这种东西,泛型函数诞生了,而以下的使用方法我是以官方 Rust Book 的文档来写
因为我想不到该怎麽解释 QwQ
pub fn Tfunc<T>(a: &[T]) {
}
以上的代码就是泛型的使用方式,那只要这样就能传入不同型式了。
但是,有时後会遇到问题。
pub fn Tfunc<T>(a: &[T]) -> T {
let mut largest = a[0];
for &i in a.iter() {
if i < largest {
largest = i;
}
}
largest
}
假如说这样编译的话,会出现
这样的错误,主要是由於使用了 "<" 所导致的
这是由於如果要做大於小於的判断,必须要实做
PartialOrd 特性,但是因为使用了泛型,所以这个型别不一定会使用此特性,
故需要让传入的 T 有这个特性
pub fn Tfunc<T: PartialOrd>(a: &[T]) -> T {
let mut largest = a[0];
for &i in a.iter() {
if i < largest {
largest = i;
}
}
largest
}
但是即使这样编译器还是会报错,这是因为
使用了largest这个变数,将 a 阵列中的值指派给了其他变数,所以也必须实现
Copy 那添加方式则是在 PartialOrd 写个 + 号後面再加 Copy。
最後的程序会像这样
pub fn Tfunc<T: PartialOrd + Copy>(a: &[T]) -> T {
let mut largest = a[0];
for &i in a.iter() {
if i < largest {
largest = i;
}
}
largest
}
这样就编译成功了!
那其实呼叫的方式就是直接让它判断传入的值是什麽。
Ex:
pub fn Tcall() {
let int_list = vec![34, 50, 25, 100, 65];
function::Tfunc(&int_list);
}
或者说,也能使用 turbofish 的语法,让编译器可以先判断是什麽型别,
不过即使使用了 turbofish 还是要在 T 上加 PartialOrd 跟 Copy 的特性
Ex:
pub fn Tcall() {
let int_list = vec![34, 50, 25, 100, 65];
function::Tfunc::<i32>(&int_list);
}
那可能你也会想说,一定要用 T 吗?
答案是,其实不用。
而这也代表了,泛型不只能使用一种型别的变数。
也就是可以定义一个 T 是 i32 一个 W 是 i64
今天的内容可能有些难涩,我自己也不常使用。
但是蛮有趣和好玩的,学起来总是有会用到的时候。
明天我想讲一些简单的闭包和基础的运算 if else match
有问题可以直接提问喔 owob
然後小小抱怨一下,我早上存的草稿竟然不见了 QQQQQ 幸好发现的早 不然就没有後续ㄌ
<<: Day 01: ML基础第一步 Python基础入门
>>: Day 7 Self-attention(一) input和output
拆弹教学 接下来的文章,会使用CDK去建置AWS上的服务,在使用CDK之前需要先安装一些程序,才可以...
前言 大家好,我是刚从硕士班毕业不到一年的社会新鲜人,目前担任小小的AI工程师。 兴趣是资料分析和深...
今天是30天程序语言研究的第十六天,由於深度学习老师多让我们上了python的进阶课程里面包括之前没...
今天要介绍的是我们学的最後一个排序法——合并排序法(Merge Sort)。 合并排序法 分成切割与...
以现有的程序码做整理 https://github.com/xhbang/C100 整理过後 mai...