不久前,我开始理解有必要专门使用C#来使我的编程经验多样化。 在对各种选项(例如Haskell,Scala,Rust等)进行了一些研究之后,选择权就落在了后者上。 随着时间的流逝,我开始注意到Rust越来越多地被单独宣传为“系统语言”,这是复杂的编译器和超负荷系统所需要的,对安全性和多线程以及Go / Python / Java / ...,虽然我很喜欢并且很成功地用它代替了我的C#主力马。

在本文中,我想谈谈为什么我认为这种趋势总体上是有害的,以及为什么Rust是一种很好的通用语言,可以用于任何类型的项目,从任何微服务开始,到日常例行脚本结束。
引言
实际上,为什么要学习一种新语言变得更加复杂? 在我看来, “战胜平庸”一词的答案与事实最接近,即:
每个人都知道用机器语言手动编写整个程序是一个错误。 但是他们不太可能理解有一个更通用的原则:如果有多种语言可供选择,那么如果选择不受其他原因的影响,那么用最强大的语言进行编程是错误的。
语言越复杂,在其帮助下制作的短语越丰富,并且可以更好地表达所需的主题领域。 因为 通常只对概念进行一次研究,然后反复应用,从投资自己的时间来研究各种可怕的词(例如“ monadic变形金刚”)(以及最好是其含义)的观点出发,然后节省您的精神力量并将其花在更多的事情上,这会带来更大的收益愉快。 因此,这是很可悲的看到一些企业的发展趋势做出特殊的“简化”的语言。 结果,这些语言的词汇量要小得多,学习起来也不难,但是要阅读“我自己买洋葱”程序就非常困难,更不用说可能的模棱两可的解释了。
基础知识
初学者通常如何了解编程语言? 他用谷歌搜索最受欢迎的语言书籍,将其拿出来阅读。 通常,它包含HelloWorld,安装编译器的说明,以及有关语言的基本信息(逐渐复杂化)。 在rasta的情况下,这是混蛋 ,第一个示例是从控制台读取一个数字并将其显示在屏幕上。 我们将如何在同一C#中做到这一点? 好吧,大概是这样的
var number = int.Parse(Console.ReadLine());
Console.WriteLine($"You guessed: {number}");
?
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = guess.trim().parse()
.expect("Please type a number!");
println!("You guessed: {}", guess);
, ( !), , .. " " "" .
:
let mut guess = String::new();
io::stdin().read_line(&mut guess)?;
let guess: u32 = guess.trim().parse()?;
println!("You guessed: {}", guess);
, , . , , . , , .
? - , , C# , , - .
.
fn search<F>(self, hash: u64, is_match: F, compare_hashes: bool)
-> RawEntryMut<'a, K, V, S>
where for<'b> F: FnMut(&'b K) -> bool
, " ", " , ", " , GC ".
. , , . :
- Each elided lifetime in input position becomes a distinct lifetime parameter.
- If there is exactly one input lifetime position (elided or not), that lifetime is assigned to all elided output lifetimes.
- If there are multiple input lifetime positions, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.
- Otherwise, it is an error to elide an output lifetime.
, , , , . . , -
struct Point(i32, i32);
impl Point {
pub fn get_x(&self) -> &i32 {
&self.0
}
pub fn get_y(&self) -> &i32 {
&self.1
}
}
, , .
- GC . C#
IDisposable
, , , GC " ", . : , ( try-with-resources Java), , foreach … , , . , , . , DI , - , 99% , .
, ( GC), ( ). : . , " ".
. , , :

. Rust 2018, . , . , .
pub struct Node {
value: u64,
next: Option<Box<Node>>,
prev: Option<Box<Node>>,
}
, , .. Box<Node>
, unique_ptr
C++. , ,
:
pub struct Node {
value: u64,
next: Option<&Box<Node>>,
prev: Option<&Box<Node>>,
}
( shared_ptr
), . : - - . " , - ", dangling pointers . -, , , - " , , ".
, " ". , , , , ( Rc
/Arc
/Cell
/RefCell
), , .
: , . , , // . : GC , WeakReferences byte[]
, , , . JS, , .
, " ", , . , , . , , . - , - . ownership'. , , , , .
. , , , .
,
error[E0382]: assign to part of moved value: `head`
--> src\main.rs:23:5
|
19 | prev: Some(Box::new(head)),
| ---- value moved here
...
23 | head.next = Some(Box::new(next));
| ^^^^^^^^^ value partially assigned here after move
|
= note: move occurs because `head` has type `Node`, which does not implement the `Copy` trait
, , . , Copy
, , - "", . , " ?".
, , compiler-driven development. , - , ", - . , . , ". , , :
fn foo<T: Copy>() {
}
fn bar<T>() {
foo::<T>();
}
, :
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> src\main.rs:6:5
|
6 | foo::<T>();
| ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
note: required by `foo`
--> src\main.rs:1:1
|
1 | fn foo<T: Copy>() {
| ^^^^^^^^^^^^^^^^^
error: aborting due to previous error
where T: std::marker::Copy
, , , !
, IDE , - , , / , - , IDE. - , , CI - - - . - IDE , , , . .
- , . , . , , , . .
, , . , , . . FFI ++ , . , . C# , " null", " KeyNotFoundException", " ", .. JS ( ) , .
, == . , , , . , , buffer overflow . , ( ).
— , , . . -, , , , , , , . , , , , C#/Java/Go/… , . , — . , , — .
. , , , , , , ", , !". , , . , , ( Java/C#/..., ), ( /++), , .
, , , , . , " ". , , - .