Based on my own experience, I wrote up some notes to help Java developers avoid stumbling stones when learning Rust: https://github.com/arnohaase/rust-for-java-devs
Feedback is appreciated and welcome!
Based on my own experience, I wrote up some notes to help Java developers avoid stumbling stones when learning Rust: https://github.com/arnohaase/rust-for-java-devs
Feedback is appreciated and welcome!
- Use enums instead of traits for polymorphism when possible. Rust traits have totally different idioms from Java interfaces.
(First, a minor nitpick about that definition. Your article is the first where I see enum
s called a form of "polymorphism". enum
s are a concrete, single, although composite type. Its just that they are "sum" or "or" types (they contain either of their variants) instead of "product" or "and" types, struct
s, which instead contain all of their fields. Of course this depends on definitions but I find it more usual to not call sum types polymorphic.)
Now, more importantly, I'd question the following piece of advice:
- If you feel you really must use traits polymorphically (and there are actually good reasons for that), always pass them around through pointers.
Conversely, the more idiomatic way (and the usual first choice) to use trait
s in Rust is with static dispatch through parametric generics. I.e., when in doubt, you should probably go with
fn foo<T: Trait>(arg: T)
instead of
fn foo(arg: &dyn Trait)
Use trait objects and dynamic dispatch only when you actually need their dynamism, or when the reduced size of the generated code would yield a performance benefit.
Be aware that a trait
has to satisfy somewhat stringent requirements in order to be able to perform dynamic dispatch (e.g. no generic methods, no taking self
by value, etc.). There are no such criteria when using parametric polymorphism.
Especially while you get started, this will probably often feel like "Leave me alone already, I know what I'm doing!". There are idioms to work with this
This is true, but I think there is more than just idioms to the core of this problem. In most cases, when one thinks what they are doing but rustc
disagrees, rustc
is right and the programmer doesn't know what they are doing. I think this perhaps surprising fact could be articulated more instead of blaming it only on differing idioms.
My point is: While getting started, treat
Vec
andBox
(and other kinds of pointers, see the separate section below for details) as part of the language core.
I'm not really sure what this piece of advice actually amounts to, but as-is it's not really true, and I have trouble seeing how it's helpful. IMO one can be aware of the fact that Vec
and Box
are library types and not think that they are language constructs without it really impeding their ability to use them. One doesn't need to know how they are implemented in order to use them, and calling them builtins could be misleading.
(Unfortunately, Box
does have a builtin/magic aspect to it, due to historical reasons, but Vec
and the other smart pointers are definitely not special in this regard.)
Arrays
[…]
And finally, arrays do not involve a pointer.
I'd find it helpful to mention slices in this section. Almost every array-like type (arrays, Vec
, boxed slices, etc.) likes to coerce itself into slices, the dynamically-sized cousins to arrays, thanks to autoref/autoderef. And pointers-to-slices as they are normally used are implemented using (and have the semantics of) fat pointers. So given their virtually unavoidable nature, it'd be better to mention them so that one won't confuse them with arrays, which have a similar typing syntax.
Well, when wanting to perform dynamic dispatch, the two main options are enum
s and trait
objects, and the latter is considered a form of polymorphism; I think that polymorphism and dynamic dispatch are related enough for enum
s to be suggested as such.
For people not knowing (true) enum
s / algebraic data types, they may try to go and reach for inheritance-like patterns when an enum
would suffice.
Definitely, that's why I'm not objecting to the "use enums by default" advice itself. I'm only finding the (implied) definition weird, not the advice in that particular bullet point.
Thanks for your detailed feedback. It helped me see where my Java perspective had muddled things. And thanks for suggesting to mention slices.
No problem!
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.