Method Signatures

Below is a Java method signature and the equivalent rust signature.

void printNum(int num);

#![allow(unused_variables)]
fn main() {
trait Example {
fn print_num(num: i32);
}
}

Things to notice: The Rust method starts with the keyword “fn” this simply indicates that a function is being declared. This is followed by the method name and the parameters to the method in parentheses. Unlike Java where the type appears on the left followed by the argument name, in Rust the name comes first followed by a : followed by the type. (Similar to how variables are declared)

If the function had a return value it would be declared on the right hand side like this:

int add(int a, int b);

#![allow(unused_variables)]
fn main() {
trait Example {
fn add(a: i32, b: i32) -> i32;
}
}

There is no void in Rust. If there isn't a return value, just don't provide one.

Just as in Java the method body is in between the curly braces.

int add(int a, int b) {
    return a + b;
}

#![allow(unused_variables)]
fn main() {
fn add(a: i32, b: i32) -> i32 {
    return a + b;
}
}

Borrowing

In Rust a variable can also be “borrowed”. When the parameter to a method is borrowed, it means the method promises not keep the parameter after the method has returned. Or anything it obtained from the parameter.

A method that takes a borrowed parameter cannot assign the parameter to a member variable. Also it can only pass that parameter to other methods which also borrow it. (Otherwise it would be able violate its contract indirectly.)

Safety monitor

I will act as the borrow checker to make sure you don't make a mistake.

To indicate a parameter is borrowed, in the method signature, place a “&” in front of the type.

As an example, in Java you might define a method isSorted() like this

boolean isSorted(List<Integer> values);

that returns a boolean indicating if a list is sorted. In Rust you would add an ‘&’ in front of the type in the method signature to indicate that it will not retain any references to the list nor its contents when the method returns.


#![allow(unused_variables)]
fn main() {
trait Example {
fn is_sorted(values: & Vec<i32>) -> bool;
}
}

It is helpful to think of ‘borrowed’ as a part of the type(i.e. “The method takes a borrowed list.”)

This declaration provides a strong and useful guarantee to the callers of a method.

Of course it would be worthless if in a newer version, the method just deleted the ‘&’ from its signature and removed the guarantee. To prevent this and to make the guarantee explicit in the caller's code, when a method that borrows a parameter is invoked, the caller puts an ‘&’ in front of the variable name being passed in. For example


#![allow(unused_variables)]
fn main() {
fn is_sorted(values: & Vec<i32>) -> bool { true }
let values = vec![1, 2, 3];
if (is_sorted(&values)) {
    //...
}
}

This is only needed if the variable being passed isn't borrowed already. (Otherwise it would be redundant, because it can only pass it to methods which borrow it.)

Passing a parameter to a method that borrows is sometimes referred to a the parameter being “lent” to the method.

Mutability

In Java a variable can be declared final. This means the value cannot be reassigned. It however does not guarentee that its contents won't change. For example if you have the method:

void process(final List<Foo> toProcess);

You can't tell from looking at the signature if the toProcess list will be modified or if the individual items in the list will be modified.

Rust avoids this ambiguity with the keyword mut. All values are unmodifyable by default, and if the variable or any of its contents are going to be changed it is prefixed with the mut keyword for eample:


#![allow(unused_variables)]
fn main() {
let mut value = 0;
value += 10;
}

Similar to variable declaration, if you want to modify a borrowed parameter, you use the mut keyword. This goes right in front of the type.

void populateCounts(HashMap<String, int> itemCounts);

#![allow(unused_variables)]
fn main() {
use std::collections::HashMap;
trait Example {
fn populate_counts(item_counts: &mut HashMap<String, i32>);
}
}

mut can be thought of a part of the type(i.e. “a borrowed mutable Hashmap” as opposed to “a Hashmap").

When ‘Borrowed’ is combined with mut, the & goes first. If you wanted to write a method to sort a list, it would take a borrowed mutable list.


#![allow(unused_variables)]
fn main() {
trait Example { 
fn sort(names: &mut Vec<String>);
}
}

This signature means sort() may change the list, but only during the invocation of the method and will retain no references to the list or its contents once the method returns.

Javadocs

Documentation is an area where Rust and Java are very similar. In Java, you might add a javdoc like this

/**
 * Computes an approximation of {@code 1/sqrt(a)} segnifigantly faster. 
 * However compared to using {@link java.lang.Math.sqrt()} the result is much less accurate.
 * @param   a   the value to compute the inverse square root of.
 * @return an approximate inverse square root of the passed parameter.
 */
public double fastInvSqrt(double a);

which can be automatically transformed into HTML documentation.

Rustdocs

Rust has rustdocs which works similarly. You could write the following:

/**
 * Computes an approximation of `1/a.sqrt()` segnifigantly faster.
 * However compared to using [`sqrt`] the result is much less accurate.
 * # Examples
 * ```
 * let a = 7.0_f64;
 * let exact = 1.0 / a.sqrt();
 * let approx = a.fast_inv_sqrt();
 * assert!((approx-exact).abs() < 1e-5);
 * ```
 */

Or instead of “/**” and a block comment, you can use “///” and line comments. So the following is equivalent:

/// Computes an approximation of `1/a.sqrt()` segnifigantly faster.
/// However compared to using [`sqrt`] the result is much less accurate.
/// # Examples
/// ```
/// let a = 7.0_f64;
/// let exact = 1.0 / a.sqrt();
/// let approx = a.fast_inv_sqrt();
/// assert!((approx-exact).abs() < 1e-5);
/// ```

(This helps with short comments as it doesn't require an extra line at the top and bottom.)

Javadocs have a number of common tags such as “@param” and “{@link }”. Below are some common ones and their Rust equivalents.

TypeJavaRust
Link to method{@link Foo#bar() }[`Foo::bar()`]
Link to URL<a href="https://google.com"> google</a>[google](https://google.com)
Code snippit{@code foo.bar()}`foo.bar()`
or
```
  foo.bar();
```
Parameter{@param foo bla bla}N/A Documented through examples and code snippits
Return@return bla blaN/A Documented through examples and code snippits
Examples<pre>
{@code
  //...
}
</pre>
# Examples
```
  //...
```
See also{@see "Bla bla"}# See Also
Bla bla
Custom tagRequires custom javac args# My custom section
//...
Bulleted list<ul>
<li>one</li>
<ul> <li>one point one</li> </ul>
</ul>
* one
** one point one

The difference between Javadocs and Rustdocs is that, to do formatting, in Java, you would inject HTML tags, where as in Rust you use Markdown syntax. So the following Javadoc and Rustdoc are equivalent __ vs __. As you can see this improves readability a lot.

To generate an view your docs you can run _. Which will put the documentation in _. When you publish your code to Crates.io (Rust’s main package repo, the docs will be published automatically.) There will be more on Crates.io and the Cargo command in chapter _.

Additional information for the doc can also be placed inside of the method, if for some reason that makes more sense from an organization point of view. So the following are equivalent __ and __.

Docs can also be hidden (If for example a feature is still being tested) like this __. Similarly you can use the _ annotation to mark them as being platform specific. For example __.

It is common practice in Rust to write a small example for how to use each function rather than documenting all of the input and output parameters like you would in Java. So instead of __ you might write __ in Rust. These examples aren’t just for show, they also get automatically turned into unit tests. For example __. This makes sure your documentation stays up to date with the code. If you want to hide a few lines of setup at the top of an example you can use _. For example __.

Macros

Ok, let’s finally get around to writing HelloWorld:

/// Prints "Hello world!".
fn main() {
    println!("Hello World!");
}

You may be wondering: “What is that exclamation point doing at the end of that function name?” The answer is println! is not a normal function but a “Macro”. Rust macros are "hygienic" so they don't have the horrifyingly dangerous properties of C and C++ macros and designed to be safe.

You can think of macros as a function that does things that functions can't normally do. In this case println! supports string templates.

fn main() {
    let name = "Ferris";
    println!("Hello {}!", name);
}

Safety monitor

The template is validated at compile time. So if you were to type

println!("Hello {}!");

or

let name = "a"; let name = "b"
println!("Hello {}!", name1, name2);

the mistake would actually cause a compile error, which is great, because it means you can't write incorrect code.

Optimizer

This gives an extra bonus of not spending any CPU time at runtime on parsing and verifying the template.

Checking a template at compile time is something a normal function couldn't possibly do. Will get into how this implemented in a later chapter. But for now you should think of an elimination mark, as an alert that there's something unusual about that function and you should read its documentation.

Another place you'll see macros is initializing collections or places where you might find “varargs" in Java. For example you can initialize a Vec with the vec! macro:


#![allow(unused_variables)]
fn main() {
let number = vec![1, 2, 3, 4, 5];
}