هو الصدأ الرهيب للغاية كما هو رسمها

منذ بعض الوقت ، بدأت أفهم الحاجة إلى تنويع تجربتي البرمجية حصريًا في C #. بعد دراسة لبعض الخيارات المختلفة ، مثل Haskell و Scala و Rust وبعض الخيارات الأخرى ، وقع الاختيار على الأخير. مع مرور الوقت ، بدأت أنبه إلى أنه يتم الإعلان عن المزيد والمزيد من الصدأ على أنها "لغة نظام" فقط ، وهو أمر ضروري للمترجمين المعقدين وأنظمة فائقة التحميل ، مع متطلبات خاصة للأمن وتعدد العمليات ، و Go / Python / Java / ... ، بينما استمتعت به واستخدمته بنجاح كبديل لعملي في C #.



في هذه المقالة ، أردت أن أتحدث عن سبب اعتبار هذا الاتجاه ضارًا بشكل عام ، ولماذا يعد Rust لغة جيدة للأغراض العامة يمكن استخدامها في أي نوع من المشاريع ، بدءًا من أي خدمات ميكروية وتنتهي بالبرمجة الروتينية اليومية.


مقدمة


لماذا ، في الواقع ، تعلم لغة جديدة ، وأكثر تعقيدًا؟ يبدو لي أن إجابة مقال "التغلب على الرداءة" هي الأقرب إلى الحقيقة ، وهي:


يعلم الجميع أن كتابة البرنامج بالكامل يدويًا بلغة الآلة يعد خطأ. لكن من غير المرجح أن يفهموا أن هناك مبدأ أكثر عمومية: إذا كان هناك اختيار من عدة لغات ، فمن الخطأ البرمجة على شيء آخر غير الأقوى ، إذا لم يتأثر الخيار بأسباب أخرى.

كلما كانت اللغة أكثر تعقيدًا ، كانت العبارات الأكثر ثراءً بمساعدتها ، وكان من الأفضل التعبير عن مجال الموضوع المطلوب. بسبب عادةً ما تتم دراسة المفاهيم مرة واحدة ، ويتم تطبيقها مرارًا وتكرارًا ، فمن المربح أكثر من وجهة نظرك أن تستثمر وقتك الخاص في دراسة جميع أنواع الكلمات المخيفة مثل "المحولات الأحادية" (وأيضًا ، ويفضل ، معناها) ، من أجل توفير قواك العقلية لاحقًا وإنفاقها على شيء أكثر لطيف وبالتالي ، من المحزن للغاية رؤية اتجاه بعض الشركات إلى إنشاء لغات "مبسطة" خاصة. ونتيجة لذلك ، فإن مفردات هذه اللغات أصغر بكثير ، وليس من الصعب تعلمها ، ولكن قراءة البرامج "بلدي لشراء البصل" أمر صعب للغاية ، ناهيك عن التفسيرات الغامضة المحتملة.


الأساسيات


كيف يتعرف المبتدئين عادة على لغة البرمجة؟ هو google هو كتاب اللغة الأكثر شعبية ، ويسحبه للخارج ، ويبدأ في القراءة. كقاعدة عامة ، يحتوي على HelloWorld ، وإرشادات لتثبيت المترجم ، ثم معلومات أساسية عن اللغة مع تعقيد تدريجي. في حالة الراستا ، هذا لقيط ، والمثال الأول هو قراءة رقم من وحدة التحكم وعرضه على الشاشة. كيف نفعل ذلك في نفس 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#/..., ), ( /++), , .


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

Source: https://habr.com/ru/post/ar434200/


All Articles