Recipe
Translate a function into Rust
Use when: you're porting a function from C++, C#, Java, Python, JavaScript or Go and want Rust that compiles and reads as Rust
Goal: a Rust function whose signature says who owns each value, what can be missing and what can fail
Taught in The translation table
Quick recipe
-
1
For each parameter: only reads it, changes it, or keeps it.
- only reads —
&T,&stror&[T]. - changes it —
&mut T. - keeps it (stores or returns it) — an owned
T.
Why: this is the one decision the source language made for you, and every borrow error later traces back to it.
- only reads —
-
2
Every
null,None,nilor "not found" result the function can produce becomesOption<T>.Example
Python's
return Nonewhen a key is absent becomes-> Option<f64>, withNonein that branch andSome(avg)in the other.Why: the caller is then forced to handle the empty case instead of discovering it at run time.
-
3
Every
throw,raiseor returned error becomes anErrin aResult<T, E>, and each call that can fail gets a?.Why: failures become part of the signature, and
?marks each place one leaves the function. -
4
Classes become structs with
implblocks, closed sets of kinds become enums, and interfaces become traits.Why: these are the rows of the table that change the design rather than the syntax, so settle them before the body.
-
5
Translate the body using the table's "new spelling" rows, compile, and fix what the compiler reports.
Why: the compiler checks the ownership choices from step 1 against how the body really uses each value.
Common mistakes
- Taking every parameter by value because the source language passed objects freely, then cloning to silence E0382.
- Translating
nulltoOptionin the signature and then calling.unwrap()on it everywhere. - Rebuilding a class hierarchy with traits when an enum would do.