Rust guide for Java developers

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!

5 Likes
  1. 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 enums called a form of "polymorphism". enums 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, structs, 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:

  1. 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 traits 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 and Box (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.

5 Likes

Well, when wanting to perform dynamic dispatch, the two main options are enums and trait objects, and the latter is considered a form of polymorphism; I think that polymorphism and dynamic dispatch are related enough for enums to be suggested as such.

For people not knowing (true) enums / 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.

3 Likes

Thanks for your detailed feedback. It helped me see where my Java perspective had muddled things. And thanks for suggesting to mention slices.

2 Likes

No problem!

1 Like