Hace algún tiempo, comencé a comprender la necesidad de diversificar mi experiencia de programación exclusivamente en C #. Después de un estudio de varias opciones, como Haskell, Scala, Rust y algunas otras, la elección recayó en la última. Con el tiempo, comencé a prestar atención a que Rust se publicita cada vez más únicamente como un "lenguaje de sistema", que es necesario para compiladores complejos y sistemas supercargados, con requisitos especiales de seguridad y subprocesamiento múltiple, y Go / Python / Java / ..., aunque lo disfruté y lo utilicé con bastante éxito como reemplazo de mi caballo de batalla C #.

En este artículo, quería hablar sobre por qué considero que esta tendencia es dañina en general, y por qué Rust es un buen lenguaje de propósito general que se puede usar para cualquier tipo de proyectos, comenzando con cualquier microservicio y terminando con la secuencia de comandos de rutina diaria.
Introduccion
¿Por qué, de hecho, aprender un nuevo idioma, aún más complicado? Me parece que la respuesta al artículo "Conquistando la mediocridad" es más cercana a la verdad, a saber:
Todos saben que escribir todo el programa manualmente en lenguaje máquina es un error. Pero es mucho menos probable que comprendan que existe un principio más general: si hay una elección de varios idiomas, es erróneo programar en algo que no sea el más poderoso, si la elección no está influenciada por otras razones.
Cuanto más complejo es el lenguaje, más ricas son las frases hechas con su ayuda, y mejor puede expresar el tema requerido. Porque los conceptos generalmente se estudian solo una vez, y se aplican repetidamente, es mucho más rentable desde el punto de vista de invertir su propio tiempo para estudiar todo tipo de palabras de miedo como "transformadores monádicos" (y también, preferiblemente, su significado), luego para ahorrar su fuerza mental y gastarlos en algo más agradable Y, por lo tanto, es muy triste ver la tendencia de algunas empresas a crear idiomas especialmente "simplificados". Como resultado, el vocabulario de estos idiomas es mucho más pequeño, y no es difícil aprenderlo, pero leer los programas "los míos para comprar cebollas" es muy difícil, sin mencionar las posibles interpretaciones ambiguas.
Los fundamentos
¿Cómo suele un principiante conocer un lenguaje de programación? Busca en Google el libro de idiomas más popular, lo saca y comienza a leer. Como regla general, contiene HelloWorld, instrucciones para instalar el compilador y luego información básica sobre el idioma con una complicación gradual. En el caso de rasta, este es un bastardo , y el primer ejemplo es leer un número de la consola y mostrarlo en la pantalla. ¿Cómo lo haríamos en el mismo C #? Bueno, probablemente algo como esto
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#/..., ), ( /++), , .
, , , , . , " ". , , - .