Karat untuk pengembang Java

Saya menyajikan terjemahan sebuah artikel oleh Evan Cameron , yang dapat membantu pengembang Java lebih memahami perbedaan dan persamaan antara kedua bahasa - yang asli ada di situs penulis . Tidak menganggap diri saya seorang pengembang Rust yang berpengalaman, saya tidak mungkin dapat berpartisipasi secara wajar dalam diskusi yang memungkinkan.


Saya ingin membuat perubahan pada blog dan meninggalkan topik yang lebih sensitif untuk fokus pada mereka. Mungkin salah satu topik paling penting yang dapat dilakukan di komunitas Rust adalah pelatihan pengembang baru. Saya sedang memikirkan pendekatan terbaik untuk mengajar Rust bagi mereka yang terbiasa bekerja dengan Jawa dan membantu untuk menguasai bahasa untuk proyek baru.


Java adalah bahasa yang saya pelajari di universitas, jadi pengalaman saya dengannya agak ketinggalan zaman dan saya belum melakukan upaya nyata untuk mengikuti bahasa tersebut. Ketika saya terakhir menulis Java, jika Anda ingin melewatkan fungsi sebagai argumen, Anda harus mendeklarasikan antarmuka baru atau membungkus fungsi Callable<T>. Sejak itu, Jawa telah berkembang pesat. Ini adalah fungsi yang ditambahkan yang memiliki efek yang jelas dari pemrograman fungsional. Saya berbicara tentang lambdas, Optionaltipe, dll. Artikel ini tidak akan berbicara tentang cara menulis di Rust atau Anda perlu membuang semua kode Java Anda. Java adalah bahasa yang bagus dengan kasus penggunaan nyata. Saya ingin membuat perbandingan Jawa dan Rust untuk programmer Rust pemula.


Motivasi bahasa


Pertama tentang tujuan setiap bahasa. Java diciptakan untuk memecahkan banyak masalah. Itu harus "sederhana, berorientasi objek dan modular" , itu harus bekerja dalam mesin virtual, menjadi portabel untuk berbagai arsitektur, dan harus memiliki kinerja tinggi. Tujuan Rust adalah untuk menjadi "sangat cepat dan efisien memori" , memiliki "sistem tipe kaya, keamanan memori, thread-safe", menghasilkan pesan kesalahan yang baik dan memiliki manajer paket bawaan.


. Rust , , . , Rust , . , , , , ( ) , (embedded) . , Rust. Rust , , (dangling) .


, Rust ( wasm frontends yew ). , , , , ( ) . .


, , Java Rust :


  • ( GC)
  • ()

; , , . , .




Rust . Rust enum struct. enum โ€” ( , ). enum Java, , Java enum, . enum , , . , , Rust null nil. Rust, .


enum Option<T> {
    None,
    Some(T),
}

Option, T. T , T. Option 2 , None (" ") , Some T. :


let a = Some("foo".to_string()); //    Option<String>

let b: Option<usize> = Some(1); //    Option<usize>,    

. , . , . , .


Rust enum match. , .


fn plus(a: Option<usize>) -> Option<usize> {
    match a {
        Some(v) => Some(v + 1),
        None => None
   }
}

, . match. cheats.rs match. if/else.


Option, - ( Some ) . , Option , .


fn plus(a: Option<usize>) -> Option<usize> {
    a.map(|v| v + 1)
}

|| {} โ€” . Rust - , , " " .



struct โ€” . , , , .


struct A {
   field: usize
}

"" .


let a: (usize, usize) = (1, 1); //    

.


struct Foo<T> {
    field: T
}


enum struct . , impl . , Rust. struct impl , :


struct Thangs {
   list: Vec<Thang>
}

struct Thang;

impl Thangs {
   // **  `new`    ,   ' '
   fn new() -> Self {
       Self {
           list: vec![]
       }
   }

   fn add_thang(&mut self, thang: Thang) {
       self.list.push(thang);
   }
}

fn main() {
  // ** &mut self   'add_thangs'   mut   
   let mut thangs = Thangs::new();
   thangs.add_thang(Thang);
}

Java, value.method() " ". , &mut self :


let mut thangs = Thangs::new();
Thangs::add_thang(&mut thangs, Thang);

, Rust . enum struct . Java - struct impl , "", ( , ). " Rust ", Java , . Java 14 "Records" () . , Java "", ( , Rust , sum product ). Java, - , , !




Rust . , . . :


struct Thing { field: usize }

fn main() {
    let a = Thing { field: 1 };
    // .. do stuff with a
}

- . , , Sized. , . , ( main) .


Java, new, , .



Box ( stdlib , Rc, Arc ..). , , ? , , , , ( ). , , , , "" Box , .


fn main () {
    let a = Box::new(Thing { field: 1 });
}

, . , . , , a a. usize , .


Box . - Java,


trait Foo {}

struct Thing;

impl Foo for Thing {}

struct OtherThing;

impl Foo for OtherThing {}

fn main () {
    let a: Vec<Box<dyn Foo>> = vec![Box::new(OtherThing), Box::new(Thing)]; //   
    //  ''     ,    
    //            Foo
    }

trait, . , . , . Rust , , , , .


, , . Rust โ€” .


.


enum List<T> {
    Nil,
    Cons((T, List<T>))
}

. List<T> Nil , Cons, . , , ?
?


    error[E0072]: recursive type `List` has infinite size
     --> src/lib.rs:7:1
      |
    7 | enum List<T> {
      | ^^^^^^^^^^^^ recursive type has infinite size
    8 |     Nil,
    9 |     Cons((T, List<T>))
      |          ------------ recursive without indirection
      |
      = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable

. help . , , . , , , N-? , , ? , . .


, .


enum List<T> {
    Nil,
    Cons((T, Box<List<T>>))
}

. , . .




Java Rust, ( ) :


enum Shape {
    Circle { radius: f32 },
    Rectangle { width: f32, height: f32 },
}

area () , , , :


impl Shape {
    pub fn area(self) -> f32 {
        match self {
            Shape::Circle { radius } => std::f32::consts::PI * radius.powi(2),
            Shape::Rectangle { width, height } => width * height,
        }
    }
 }

Java . Rust pub ( ), ( ). , Rust reference.


. Java Shape Circle Rectangle, area. Rust Java, :


  • Shape:
    • Java: Shape
    • Rust: Shape , ( match , )
  • Shape:
    • Java: "" Shape, ,
    • Rust: impl

' ' (expression problem). . enum Rust / Java. , Rust match enum. : ยซ , ?ยป


, .


trait Area {
    fn area(self) -> f32; //          ( i32)
}

struct Rectangle {
    width: f32,
    height: f32
}

struct Circle {
    radius: f32
}

impl Area for Rectangle {
    fn area(self) -> f32 {
        self.width * self.height
    }
}

impl Area for Circle {
    fn area(self) -> f32 {
        std::f32::consts::PI * self.radius.powi(2)
    }
}

, Circle Rectangle, perimeter, :


trait Perimeter {
    fn perimeter(self) -> f32;
}

impl Perimeter for Rectangle {
    fn perimeter(self) -> f32 {
        2. * (self.width + self.height)
    }
}
//  ..

. , , "" " ".


fn do_something<T: Perimeter + Area>(shape: T) { //   ,    Perimeter  Area
        unimplemented!() // :   
        //        
    }


Rust . , , Java. , . Java , Rust . , . , , . Future , Iterator IntoIterator for..in, Index [], Add, Sub, Mul . , Add


Add std.


pub trait Add<Rhs = Self> { // 1
    type Output; // 2
    fn add(self, rhs: Rhs) -> Self::Output; // 3
}

Std Add Rhs, Self, .. (1). ยซ ยป Output (2) add, self ( self) rhs Rhs ( ) , Output (3).


use std::ops::Add;

#[derive(Debug)]
struct Content<T> { // 1
    val: T,
}

impl<T> Add for Content<T> // 2
   where
    T: Add, // 3
{
    type Output = Content<<T as Add>::Output>; // 4
    fn add(self, rhs: Content<T>) -> Self::Output {
        Content {
            val: self.val + rhs.val,
        }
    }
}

fn main() {
    let a = Content { val: 2 };
    let b = Content { val: 5 };
    println!("{:?}", a + b); // Content { val: 7 }
}

Content, T (1). Add , Content Add (2), , Content Add (3). , Output Content Output T, Add (4). , , , . , , . , " " , Rust. , Rust , ( ), .


, Sized , fn foo<T>(t: T) -> T, T: Sized. T: ?Sized, T . .



Java . OO Rust, Java. Java โ€” (subtype polymorphism), Rust โ€” (ad-hoc) . , , , ( <T: Trait> ).


, "" . , enum struct, impl. impl , . , , -. .


Rust . str, String, OsStr, OsString, CString CStr ( - ?). , str String, โ€” . , , ?


&str , &str &String , String Deref<Target=str> ( Target= , Target " "). .


fn foo<S: AsRef<str>>(s: S) {
    unimplemented!()
}

AsRef โ€” stdlib. :


trait AsRef<T>
  where
    T: ?Sized,
{
    fn as_ref(&self) -> &T;
}

, T, , &T. foo String,


let a = String::from("stuff");
foo(a);

? , ( ). Rust stdlib.


, . , , . , . Java ( , Java ). Java , . ยซ ยป. Rust , .



, , . , - . , , . Rust , ! , Rust .


.


: Java Rust


Java , . , . - Java , .. . , , Java , ( Java <T> <T extends Class> ), Java , (type erasure). , Object -. Java, , โ€” . - vtable, .


Rust . foo foo , foo . , foo 4 AsRef<str>, 4 . ยซยป. , Rust " ". ( Box), Objectatau transfer tabel virtual jika kita tidak menginginkannya. Perlu dicatat bahwa kelemahan dari metode ini adalah ukuran kode akhir dan waktu kompilasi. Bergantung pada berapa banyak varian fungsi yang berbeda dan berapa banyak implementasi yang perlu kita hasilkan, semakin banyak kode yang harus melalui LLVM, meningkatkan waktu kompilasi dan meningkatkan jumlah kode yang sebenarnya dihasilkan.


Kontak Evan Cameron: surat , github , twitter , ditautkan dalam


Diskusi lambat tentang terjemahan Rust dilakukan dalam obrolan telegram untuk terjemahan Rust .


All Articles