<-- Home |--rust |--rfe

RFE-001: 工程师(粗)Rust入门之(不可变)变量

碎碎念

粗:什么!工程师也要学Rust?!

强:是啊,听说Rust很厉害。

粗:可是我听说Rust很难学耶!

强:嗯,也没指望你们学会,只是KPI要求……数智赋能嘛,有一个分支就是要求学习新技术,开辟新路线,找到新niche market。

粗:那我学?

强:总不能我学啊,你不是工程师吗?

粗:可是我听说Rust很难学耶!

强:进入循环对话模式了吗……

粗:事已至此,只能报名我徒弟躺平工程师小龙学了……

为什么选择Rust?

就是无聊而已,其实对于搞C/C++偏硬件的工程师来说,Rust真是一点都不难。而且,Rust的工具链相当不错,生态什么硬件工程师根本不关心。而且Rust居然还提供了一大堆C没有的玩意(数据结构、抽象工具),万一以后可以用,还是挺好的。

用工程师的话说,Rust就是追求既要又要:

  • 不要增加运行时开销
  • 达到一定程度的内存安全

内存安全是一个老话题,C/C++程序员都是写内存泄漏的专家,野指针、悬垂指针、缓冲区溢出这些都是家常便饭。

这也是为什么业务编程有很大一部分(并不是全部,C/C++也有很多业务编程)首先是跑到了Java,后面C#也半吊子地跟上,虽然微软始终是半糖主义随机正义撤退……其实Java也听惹人讨厌地,所以Ruby on Rails、Python/Django这些动态语言框架也就流行得不要不要的……

乃至动态/虚拟机语言搞到天怒人烦的地步,搞出Go这种玩意来。你还别说,Go还真挺受欢迎的,实在是残疾儿童欢乐多。

这些语言有一个共同特征:GC(垃圾回收)。GC的好处是程序员不需要操心内存管理,坏处是程序员不需要操心内存管理。

其实GC没啥高大上的,Lisp这么老的语言,GC鼻祖。

我全都要!

Rust原神启动:我既不搞GC,也要内存安全!

这当然也不是什么新鲜事儿,Cyclone语言就搞过类似的东西。我给你甩一串神秘代码10.1016/j.scico.2006.02.003你自己体会赶快说好人一生平安……这玩意发了一大堆文章,是基于Region-based memory management的,理论上还是有一把刷子的,还有个很好的文章:Linear Regions Are All You Need,这篇文章特别推荐去看看,看完一定要来谢谢我。但是不能说我谢谢你啊这类的话。

Cyclone代码看起来跟C是一模一样的……最后因为成员都干别的去了,大概2011年就都不搞了……

Rust的内存安全是基于Ownership(所有权)的概念,Ownership的概念其实也不是Rust首创的,之前有很多语言都搞过类似的东西。C++中间要搞智能指针(Smart Pointer)来管理内存,Rust的Ownership其实就是把智能指针的概念提升到了语言层面。C编程需要都要讲生命周期,不过是靠程序员自己脑补,Rust把生命周期的概念也提升到了语言层面。

Rust的变量与浮点数

工程师Rust之路(完结)

对于工程师而言,装上Rust的工具链之后,首要的就是想当作计算器用,算数字。

那么Rust支持算什么数据呢?

我们先搞个1 + 1试试:

1fn main() {
2    println!("1 + 1 = {}", 1 + 1);
3}

很好,rustc opo.rs编译通过了,./opo运行也没问题。

1>./opo
21 + 1 = 2

这就是说,工程师那点东西,Rust已经完全拿捏。我们已经完全学会了工程师版Rust。

««全系列终结»»

哦,不对,我们高级工程师比这个还是要强一点点,强在哪里呢?我们是要算浮点数的!

1fn main() {
2    println!("1.0 + 1 = {}", 1.0 + 1);
3}

同样的,rustc opo-float.rs

 1rustc opo-float.rs
 2error[E0277]: cannot add an integer to a float
 3 --> opo-float.rs:2:34
 4  |
 52 |     println!("1.0 + 1 = {}", 1.0 + 1);
 6  |                                  ^ no implementation for `{float} + {integer}`
 7  |
 8  = help: the trait `Add<{integer}>` is not implemented for `{float}`
 9  = help: the following other types implement trait `Add<Rhs>`:
10            `&f128` implements `Add<f128>`
11            `&f128` implements `Add`
12            `&f16` implements `Add<f16>`
13            `&f16` implements `Add`
14            `&f32` implements `Add<f32>`
15            `&f32` implements `Add`
16            `&f64` implements `Add<f64>`
17            `&f64` implements `Add`
18          and 56 others
19
20error: aborting due to 1 previous error
21
22For more information about this error, try `rustc --explain E0277`.

好的,小龙你看打了,刚才这就是错误的演示!让我们一起啊看看,到底是什么问题(金山词霸中……)。没有实现浮点和整数的加法(四六级水平全开中……)。

也就是说,Rust不允许不同类型的数据直接进行运算,这就是Rust的类型系统在起作用。那么我们高级工程师头疼医头脚痛医脚的技能大作,把1改成1.0试试:

1println!("1.0 + 1.0 = {}", 1.0 + 1.0);

嘿嘿嘿!

工程师之魂:计算浮点数

前面已经给我徒弟小龙一起学习过,Rust是一个强类型的语言,常见的数据类型包括整数类型(如i32u64)、浮点类型(如f32f64)等。变量在使用前必须声明类型,或者通过初始化值让编译器推断类型。

而且我们还一起学会了,整数只能跟整数计算,浮点数只能跟浮点数计算。还有最后一个问题,数学函数在哪里?

1fn main() {
2    println!(" sin(pi/16) = {}", (std::f64::consts::PI / 16.0).sin());
3}
1>./rust-math
2 sin(pi/16) = 0.19509032201612825

好了,我们又一次成功了!然来Rust比我们想象的更容易,小龙,看到没有,这就是面向对象(.sin())的威力!小龙,接下里你看我计算一个高端的:任意三角形的两边及夹角求第三边!

1fn main() {
2    println!(
3        "∠pi/16-(2.0,4.0) => {}",
4        (2.0_f64.powi(2) + 4.0_f64.powi(2)
5            - 2.0 * 2.0_f64 * 4.0_f64 * (std::f64::consts::PI / 16.0).cos())
6        .sqrt()
7    );
8}
1.\rust-triangle.exe
2∠pi/16-(2.0,4.0) => 2.075436222471872

哈哈哈!小龙,你看,师傅🐂🍺🙅‍🐂🍺,Rust不过如此!!!给点表情,年轻人要活泼一点……

变量

如果你是我这种高级工程师,所需要的程序设计不过就是上面的这些,有一个println!和高端的浮点数据(f64)就够了。

但是,如果你是小龙这样的初级工程师,可能还需要了解一下变量的概念。因为我还要不听问不同的值算出来是什么样的。

所以,我就给小龙布置了一个任务,让他写一个程序,计算个十组八组不同的三角形第三边长度问题。

小龙毕竟是West Jiaotong University的毕业生,虽然是躺平工程师,能力还是很强的。

1fn main() {
2    let a: f64 = 2.0;
3    let b: f64 = 4.0;
4    let angle: f64 = std::f64::consts::PI / 16.0;
5    let c_squared = a.powi(2) + b.powi(2) - 2.0 * a * b * angle.cos();
6    let c = c_squared.sqrt();
7    println!("第三边长度 c = {}", c);
8}

小龙写完之后,运行程序,发现结果是正确的。

1>./rust-triangle2
2第三边长度 c = 2.075436222471872    

毕竟是初级工程师,还要搞很多中间变量来把结果存放着,不像我们高级工程师,大脑里存着所有东西,只要拍脑袋的力气够大就行了。毕竟是年轻人,变量就变量吧……

不过变量这个名字就够奇怪的,明明这里面都是不变量……

大概到这里,我觉得小龙的Rust知识已经过于重组,完全满足工程项目所需了。

««全系列终结»»

题外话:现在你们看到,Rust果真是内存安全,完全任何问题,甚至,小龙的程序中都可以不标记很多变量的类型,Rust编译器都能自动推断出来。还是先进的技术!原神启动!

接下来,小龙,你把我们上次的卫星轨道预测计算SGP4-XP全部用Rust重写一遍吧,反正也很简单,就是加减乘除,都用f64就行了。

现在是5点多钟……师傅今天实在是太累了……回去修仙哦不休息去了,你只需要在明天早上8点之前把代码写完就行了!!!不着急,慢慢写……

SGP-EQ-Example-1 SGP-EQ-Example-2 SGP-EQ-Example-3

下略……

展望

其实最根本的编程的应用,不过如此,纸笔、算盘、卡西欧计算器、Fortran、C/C++这些老牌工具,早就能干这些事儿了。Rust不过是把这些东西用一种更现代的方式表达出来而已。

但是接下来,我们要进入深水区,让小龙学习更高级的、真正能变的变量~~~和分支判断、循环这些控制结构,使之能够真正编写复杂的程序。


文章标签

|-->rust |-->tutorial |-->beginner |-->engineering


GitHub