1.1 Comments 
Tags: rust, tutorial, motivation, markdown
Published: 2021-03-11 17:05:17

This week we're gonna explore comments in Rust. Commenting in Rust serves a couple of purposes. Using *regular comments* we can explain how we implemented a solution or why we chose to implement that solution. Using *documentation comments* ("doc comments") we can document our code by explicitly describing how to use our code and how our code may behave in certain situations. Doc comments also provide us with some awesome functionality—Rust is able to auto-generate documentation based on the doc comments we made in our code. Whether we use *regular comments* or *doc comments*, Rust gives us two powerful conventions to explain our code to other humans who write code.

Let's see how we can take advantage of Rust's comment syntax rules to document our code as we write it. 

> Rust's commenting and documentation conventions 
> emphasize [using line comments over block comments]
> [rfc-use-line-comments]. Because of this, I'm gonna cover line comments and include some examples of 
> block comments at the end.

## Regular Comments

We can create regular comments in Rust using `//` syntax.

```rust
// This is a line comment
let x = 5 + 5;
```

## Documentation Comments

Inner Line Documentation Comments use `//!` and are useful for describing high level functionality of an entire `crate`. 

We can think of a crate in Rust as either a *binary* or *library*. 

A *library* crate contains useful utilities we can use within our projects (i.e. [`rand`], which is a library crate containing utilities for number generation

A *binary crate* which is an executable, a machine code representation of the code we write. (i.e. an app, website, any program we create!)

Inner Line Documentation Comments use `//!` and are mostly used to provide top-level documentation to a crate you create. 

[`usize`] lets our function know our `number` argument has to be number between `0` and `18446744073709551615`. The `usize` after `->` let's Rust know this function returns a number with the type of `usize`

```rust
	// ./src/lib.rs

	//! This inner documentation line comment documents our `./src/lib.rs` file.
	//! We've created a rust library crate which means `./src/lib.rs` 
        //! is the entry point of our code.
	//! When we compile our code, it starts with this file!
	
	fn add_one(number: usize) -> usize {
		return number + 1
	}
```

Outer Line Documentation Comments use `///` and are the preferred way to document any other code you write.

```rust
	// ./src/lib.rs

	//! This inner documentation line comment documents our `lib.rs` file.
	//! We've created a rust library crate which means `lib.rs` is the 
    //! entry point of our code.
	//! When we compile our code, it starts with this file!
	

	/// This function will add the number you pass in by 1
	/// It will then return that number

	/// This is an outer documentation line comment because it exists before
	/// the function `add_five` we have defined below
	fn add_one(number: usize) -> usize {
		return x + 1;
	}
```

We are using **Inner Line Documentation Comments** to document the **inside** of our `./src/lib.rs` file and **Outer Line Documentation Comments** **outside** of our `add_one` function to document our `add_one` function. 

---

Using any form of *documentation comment* we can document our code using [Markdown][Markdown in Rust], specifically the [CommonMark specification]. 

By supporting Markdown, Rust has given us a powerful, uniform convention to help us document our code. To really illustrate this, let's look at the documentation for Rust's standard library, [`std`]

We're currently looking at Rust's `std` or 'standard' library. Any project we create automatically have access to the entire standard library. 

You should see a page that looks like this:

![std library crate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/99cbgwdt7hagbq0igzt1.png)
 
Do you see the `[src]` in the top right corner? I want you to open that link in a new window and compare the two, maybe like this:

![std and std src comparison](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t2bprhc2l9moddel3zc.png) 

Do you notice anything? 

Do you see how the `std` library uses Inner Line Documentation Comments (`//!`) to document the top-level of the `std` library? 

Do you see how each line with Inner Line Documentation Comments looks similar to the `std` library's generated documentation from those comments?

We can even see some Markdown used in creating an unordered list:

![unordered list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l7p5b3i5gs24t3zu88fz.png)
 
Built into Rust we get a powerful convention for documenting the code we write! 

---

Now that we know the basics of using *documentation comments* we'll use `cargo` to create a library and some documentation for it.

> You'll want to have Rust with the `cargo` package 
> manager installed on your local computer to get the 
> most out of this exercise, but you can also follow 
> along!

> Check to see if `cargo` is installed by running:
>
> `cargo --version`

Rust comes with a bunch of tools when you install it, one of them being `rustdoc`. `rustdoc`'s purpose is to build documentation from our crate's entry point which is called our "crate root". When we build the documentation `rustdoc` turns it into HTML, CSS, and Javascript. `rustdoc` is a more low-level than `cargo`, and luckily `cargo` has commands that act as wrappers for `rustdoc` to make generating our documentation easier.  If you want to learn more about `rustdoc`, you can look at [the `rustdoc` book].

Now before we generate our documentation website, let's write a simple library with a couple of addition functions. Then we'll document it using all three types of comment!

Let's run `cargo new addition_functions --lib` to create our new Rust library. Then we'll run `cd addition_functions`. Open this in your favorite code editor and then open the `./src/lib.rs` file and delete the code inside. 

We should see something like this:

![1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tbj8t2iydauox54uhwrq.png)

Congrats! You've just created a Rust library crate. A Rust library includes functionality that may be used by a binary crate or other library crates. For example, the `std` library handles the creation of built-in types for rust. We don't go off on our own and try to build an `integer` type, because it would most likely be a waste of time. Rust already provides us with multiple `integer` types in it's `std` library crate, so let's use them!

From here let's create a couple of functions. In `[./src/lib.rs](http://lib.rs)` we'll add this code:

![2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h61dqtcx9o0ejw5dkiiz.png) 

[`pub`] makes our function public so that it will be included in documentation.

And then we'll run `cargo doc --open`. This command will generate our documentation and open it locally in the browser.

![addition_functions_doc](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3zovs8tr66vvxi8vdwmf.png) 

You can also run `cargo doc` to build documentation and not open it in a web browser. 

When we use `cargo`, our documentation website is built within our `./target/doc/[name-of-library]` folder, the entry point being the `index.html` file. 

This means an alternative to running `cargo doc --open` would be running `cargo doc` and then  `open target/doc/[name-of-library]/index.html`(in our case `[name-of-library]` will be `addition_functions`

So we have our two adding functions, now we should write some documentation to describe how they work. Let's use all three types of comments to document the purpose of our library.

Our Inner Documentation Line Comments to document our entire library: 

![3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8g1fepbt6gi13s23sul.png) 

Our Outer Documentation Line Comments to document our functions:

![4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lotlqc17hbupvjgsxtov.png) 

And finally some Regular Comments:

![5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgfo89bvq75llrl5aezd.png) 

[Here is a full code] 

Now that we've added some comments, lets re-build our documentation using `cargo doc --open`

![6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qjndvh59glnj9rv8eqa.png) 

We can see our Inner Documentation Line Comments (`//!`) which describe the entirety of our library. This is because they are top level within our `[./src/lib.rs](http://lib.rs)` file. Rust convention dictates that we only use this type of comment to give an overview of our crate's functionality—a general explanation of what functionality our crate provides.

Now below that we see our two functions with their Outer Documentation Line Comments (`///`). Remember, they are called Outer Documentation Line Comments because they are just before or "outside" of the code they comment on. In this case we're commenting on the `add_five` and `add_ten` functions respectively. Let's click the `add_five` function.

![7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0og71oenk64h39iaxe97.png) 

Now we see our function signature in addition to the rest of the outer documentation comments we wrote! 

Finally, we'll check out our source code by clicking `[src]` in the top right corner. Now we'll be able to see our regular comments:

![8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvxmmfmfqdb3z96xea2h.png) 

Remember, regular comments are useful for other developers working on/developing the library crate, while Outer/Inner Line Documentation is more useful for developers who are using your library crate.

This is a lot. We haven't even gotten to understanding types in Rust, but it seems very intentional to me that Rust By Example teaches commenting just after "Hello, World!", its first section. Commenting is a way to bridge the communication gap between developers, whether we comment on a line of code or create documentation for an entire library. Comments create documentation in Rust, and documentation can mean the difference between spending 5 minutes on a problem or 5 hours. Rust has excellent documentation. As we keep learning let's take advantage of it. Let's apply the knowledge we've learned today to search documentation for answers and learn Rust as solidly as we can.

# EXTRA STUFF

We can search for documentation on [docs.rs], an open source website that hosts all documentation for crates added to [crates.io]

Now let's give our documentation a little flair and learn about some of the ways we can make it more explicit, give it some minimal Markdown styling, and even some alternative syntax.

## An Alternative Commenting Syntax

Both inner and outer documentation comments are syntactic sugar for the built in [`[doc=""]`](https://doc.rust-lang.org/rustdoc/the-doc-attribute.html) attribute. We can use them interchangeably like so:

| Type of Comment                   | w/o Syntactic Sugar                             | w/ Syntactic Sugar                         |
|-----------------------------------|-------------------------------------------------|--------------------------------------------|
| Inner Line Documentation Comments | #[doc="This is an inner documentation comment"] | /// This is an inner documentation comment |
| Outer Line Documentation Comments | #![doc"This is an outer documentation comment"] | //! This is an outer documentation comment |

## Markdown Syntax, Code Examples, and Testing

[Some API Conventions]

Rust crates include some common headings as convention (Errors, Safety, Example) we can use to describe how our code may behave in common use cases. Let's create an Examples header for our `add_five`, write a code example, and then test it.

Using Markdown syntax we can create a heading and called "Examples" above our `add_five` function. Let's see what that looks like:

{% gist https://gist.github.com/QMaximillian/fb95c09439af367d1bf898c7a97bf68f %}

Markdown will default to Rust, but it never hurts to be explicit about the language we are using.

From here, let's use the `assert_eq!` macro to see if our function is working as intended. If the two arguments we pass in are equal, the test will pass. Otherwise, it will fail.

{% gist https://gist.github.com/QMaximillian/fec0d9f2f7d3c20b4e31d94e60681196 %}

Now if we run `cargo test --doc`, we'll only run our documentation test cases. In our console we'll see if the test cases passed or failed. 

![9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hk57le84pjihpzehryqd.png) 

Looks like our test cases passed!

If you're feeling up to it, why don't you write some simple Example documentation for the `add_ten` function like we did above, for practice!

---

## Block Comment Examples

### Inner Block Documentation Comments

```rust
/*!
		This library has two functions
		that will add an integer to the integer you pass in.
!*/

pub fn add_five(number: usize) -> usize {
    return number + 5;
}

pub fn add_ten(number: usize) -> usize {
    number + 10
}
```

### Outer Block Documentation Comments

```rust
/**
		Adds 5 to the integer passed in.
**/
pub fn add_five(number: usize) -> usize {
    return number + 5;
}

/**
		Adds 10 to the integer passed in.
**/
pub fn add_ten(number: usize) -> usize {
    number + 10
}
```

### Regular Block Comments

```rust
pub fn add_five(number: usize) -> usize {
		/* 
			 I chose to return explicitly here
		   for clarity in a blog where we're learning
			 how to write comments.
    */ 
    return number + 5;
}

pub fn add_ten(number: usize) -> usize {
		/* 
			 I chose not to return explicitly here
		   because we now know we can return explicitly in
       Rust, but we can also not include a ";" (semi-colon)
       and Rust will return that expression.
    */ 
    number + 10
}
```

---

Here's a handy table to remember all three types of comment, whether they are in *line or block *****form.

| Type of Comment                   | Line Comments (Very Common) | Block Comments (Uncommon) |
|-----------------------------------|-----------------------------|---------------------------|
| Regular Comments                  | `//`                        | `/* ... */`               |
| Inner Line Documentation Comments | `///`                       | `/** ... **/`             |
| Outer Line Documentation Comments | `//!`                       | `/*! ... !*/`             |





[`std`]: https://doc.rust-lang.org/stable/std

[docs.rs]: https://docs.rs/

[crates.io]: https://crates.io/

[CommonMark specification]: https://commonmark.org/help/

[rfc-use-line-comments]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#use-line-comments

[Markdown in Rust]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#using-markdown-1

[the `rustdoc` book]: https://doc.rust-lang.org/rustdoc/index.html

[`rand`]: https://docs.rs/rand/0.7.3/rand/

[`usize`]: https://doc.rust-lang.org/std/primitive.usize.html

[`pub`]: https://doc.rust-lang.org/std/keyword.pub.html

[Here is a full code]: https://gist.github.com/QMaximillian/196c3898835fbcbc4432f2e97f2e98ee

[Some API Conventions]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md