さびは塗られているほど怖い

少し前に、プログラミングの経験をC#のみで多様化する必要性を理解し始めました。 Haskell、Scala、Rustなどのさまざまなオプションを検討した結果、後者が選択されました。 時間が経つにつれて、セキュリティとマルチスレッド、およびGo / Python /に特別な要件を持つ複雑なコンパイラとスーパーロードシステムに必要な「システム言語」としてのみRustが宣伝されていることに注意を払い始めました。 Java / ...、私は楽しんでおり、C#の主力製品の代替品として非常にうまく使用していました。













この記事では、なぜこの傾向が一般的に有害であると考えるのか、そしてRustがあらゆる種類のプロジェクトに使用できる優れた汎用言語である理由、マイクロサービスから始めて日常のスクリプト作成で終わることについて話したかったのです。







はじめに



なぜ実際に、新しい言語を習得するのでしょうか? 「平凡を征服する」という記事への答え 、真実に最も近いように思えます。







誰もが、プログラム全体を機械語で手動で書くのは間違いであることを知っています。 しかし、彼らはより一般的な原則があることを理解することはあまりありません:複数の言語の選択がある場合、他の理由に影響されない限り、最も強力な言語以外のものでプログラミングするのは誤りです。

言語が複雑であればあるほど、その助けを借りて作成されるフレーズが豊富になり、必要な主題分野をよりよく表現できるようになります。 なぜなら 概念は通常一度研究され、繰り返し適用されます。「モナド変換器」のようなあらゆる種類の恐ろしい言葉(そして、できればその意味)を研究するために自分の時間を投資するという観点からは、はるかに利益があります。楽しい。 したがって、一部の企業が特別に「単純化された」言語を作成する傾向を見るのは非常に悲しいことです。 その結果、これらの言語の語彙ははるかに少なく、学習することは難しくありませんが、「あいまいな解釈」は言うまでもなく、「自分で玉ねぎを買う」というプログラムを読むことは非常に困難です。







基本



初心者は通常、プログラミング言語をどのように知るのですか? 彼は最も人気のある言語の本をグーグルで検索し、それを引き出して読み始めます。 原則として、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), ( ). : . , " ".









. , , :













. 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#/..., ), ( /++), , .







, , , , . , " ". , , - .








All Articles