أقدم ترجمة لمقالة كتبها إيفان كاميرون ، والتي يمكن أن تساعد مطوري جافا على فهم الاختلافات والتشابهات بين اللغتين بشكل أفضل - الأصل موجود على موقع المؤلف . لا أعتبر نفسي مطورًا راستًا ذا خبرة ، من غير المحتمل أن أتمكن من المشاركة بشكل معقول في المناقشات المحتملة.
أود إجراء تغييرات على المدونة وترك مواضيع أكثر حساسية للتركيز عليها. ربما يكون أحد أهم الموضوعات التي يمكن القيام بها في مجتمع Rust هو تدريب المطورين الجدد. كنت أفكر في أفضل طريقة لتدريس Rust لأولئك الذين اعتادوا على العمل مع Java والمساعدة في إتقان اللغة لمشروع جديد.
كانت لغة جافا هي اللغة التي درستها في الجامعة ، لذا فإن تجربتي معها عفا عليها الزمن إلى حد ما ولم أجد أية محاولات حقيقية لمواكبة اللغة. عندما كتبت جافا للمرة الأخيرة ، إذا كنت ترغب في تمرير وظيفة كوسيطة ، كان عليك إعلان واجهة جديدة أو لف الوظيفة Callable<T>
. منذ ذلك الحين ، قطعت Java شوطًا طويلاً. هذه وظائف مضافة لها تأثير واضح من البرمجة الوظيفية. أنا أتحدث عن اللمداس Optional
والأنواع وما إلى ذلك. لن تتحدث هذه المقالة عن كيفية الكتابة في Rust أو أنك بحاجة للتخلص من جميع رموز Java الخاصة بك. جافا هي لغة رائعة مع حالات الاستخدام الحقيقي. أريد إجراء بعض المقارنات بين Java و Rust لمبرمج Rust المبتدئين.
الدافع اللغوي
أولاً حول أهداف كل لغة. تم إنشاء Java لحل العديد من المشاكل. كان يجب أن تكون "بسيطة وموجهة نحو الكائنات ووحدات" ، ويجب أن تعمل في آلة افتراضية ، وأن تكون محمولة لمختلف الهياكل ويجب أن يكون لها أداء عالي. تتمثل أهداف Rust في أن تكون "سريعة بشكل لا يصدق وكفاءة في الذاكرة" ، وأن يكون لديها "نظام غني بالنوع ، وأمن للذاكرة ، وآمن لمؤشر الترابط" ، وأن تنشئ رسائل خطأ جيدة وأن يكون لديها مدير حزم مدمج.
هناك بعض الاختلافات بينهما. أداء رست مرتفع ، مشيراً إلى عدم وجود بيئة وقت تشغيل ، فضلاً عن أمان الذاكرة إلى جانب نظام قوي من النوع. هذه هي المجالات التي يتألق فيها الصدأ حقًا ؛ رمزه منتج وآمن. الخوادم التي تحتاج إلى معالجة عدة آلاف من الطلبات في الثانية ، والتطبيقات التي تحتاج إلى أن تكون سريعة وتعمل مع مساحة صغيرة من الذاكرة ، أو نظام تشغيل (نظام تشغيل) أو رمز يعمل على جهاز مضمن. يمكن القيام بهذه الأشياء بلغات أخرى ، ولكن هذه هي المنطقة التي تم إنشاء Rust من أجلها. يسمح الصدأ بذلك ، بينما يمنع أشياء مثل تجاوزات المخزن المؤقت أو التعلق أو المؤشرات الخالية.
, Rust ( wasm frontends yew ). , , , , ( ) . .
, , Java Rust :
; , , . , .
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());
let b: Option<usize> = Some(1);
. , . , . , .
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 {
fn new() -> Self {
Self {
list: vec![]
}
}
fn add_thang(&mut self, thang: Thang) {
self.list.push(thang);
}
}
fn main() {
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 };
}
- . , , 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)];
}
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;
}
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) {
unimplemented!()
}
Rust . , , Java. , . Java , Rust . , . , , . Future
, Iterator
IntoIterator
for..in
, Index
[]
, Add
, Sub
, Mul
. , Add
Add
std.
pub trait Add<Rhs = Self> {
type Output;
fn add(self, rhs: Rhs) -> Self::Output;
}
Std Add
Rhs
, Self
, .. (1). « » Output
(2) add
, self
( self
) rhs
Rhs
( ) , Output
(3).
use std::ops::Add;
#[derive(Debug)]
struct Content<T> {
val: T,
}
impl<T> Add for Content<T>
where
T: Add,
{
type Output = Content<<T as Add>::Output>;
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
, 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
), Object
أو نقل جدول افتراضي إذا لم نرغب في ذلك. وتجدر الإشارة إلى أن عيب هذه الطريقة هو حجم الكود النهائي ووقت التجميع. اعتمادًا على عدد المتغيرات المختلفة لوظائفنا وعدد عمليات التنفيذ التي نحتاج إلى إنشائها ، يجب أن يمر المزيد من التعليمات البرمجية عبر LLVM ، مما يزيد من وقت التجميع ويزيد من كمية التعليمات البرمجية التي تم إنشاؤها بالفعل.
اتصالات إيفان كاميرون: mail ، github ، twitter ، linkedIn
تجري مناقشة بطيئة لترجمات Rust في دردشة برقية لترجمات Rust .