- web: https://ashleygwilliams.github.io/a-very-brief-intro-to-rust/#1
- github: https://github.com/ashleygwilliams/a-very-brief-intro-to-rust
made by @ag_dubs who is, at best, an advanced beginner in Rust
Concepts are more important, but sometimes you need a little boost to get to a point where the concepts make sense.
The best way to install Rust is with rustup. rustup is a Rust version manager. To install it type:
curl https://sh.rustup.rs -sSf | sh
To keep your rust up-to-date with the latest stable version of rust, type:
rustup update
To check which version of Rust you have type:
rustc --version
There are many ways to setup a project in Rust, but this is the simplest.
- Create a repository on Github
- Clone the repository
cd
into the repository directory- Type
cargo init .
- Use
--bin
if you are not writing a library
This will create several files and folders for you automatically:
Cargo.toml
: metadata about your project and its dependencies.gitignore
: ignores compiled files built by Rustsrc/lib.rs
orsrc/main.rs
: where your Rust code goes
There are 2 main types of projects you can make in Rust: a library and not a library.
If you are writing a library, it means you intend for your
code to be used in someone else's application as a crate or module.
If you want to do this, you should use a lib.rs
.
If you are writing a not library, it means that you'd like
to write code that compiles into a binary that someone can run. If you
want to do this, you need to use a main.rs
. Inside the main.rs
you
should have a main
function that looks like this:
fn main() {
// your app code goes here
}
Cargo is a tool that helps you develop Rust. It does several things:
- Runs tasks:
cargo build
(compile your app),cargo test
(test your app),cargo run
(run your app) - Start a project:
cargo new
,cargo init
Cargo is also the package manager for Rust. This means that you can use Cargo to install and manage bits of other people's code.
- A package in Rust is called a Crate.
- You can find Crates on http://crates.io
- You list the Crates you want to use in the
Cargo.toml
file - Your app keeps track of what crates you are using in the
Cargo.lock
file
To get started using Rust you'll probably want to assign values so that you can use them. To do this in Rust:
let name = "ashley";
let age = 30;
If you want to make a constant, you must specify a type:
const FAVENUM: u32 = 6;
There are a lot of types, but just to get you started:
u32
: unsigned 32-bit integeri32
: signed 32-bit integerString
and/or&str
: more on these belowbool
: a boolean
Strings in Rust are a lot more complicated than you might be used to if you are coming from another language, in particular, interpreted languages like Ruby or JavaScript. Here's some key points:
- "my string" is not a
String
. it's astr
. the difference between aString
and astr
is how they are allocated. Don't worry about that right now. - pretty much always use
str
with an&
, as&str
. - You can turn a
&str
into aString
by usingto_string()
orString::from()
. You want to do this becauseString
has a ton of awesome convenience methods.
- add a
&str
to aString
usingpush_str()
let mut realstring = String::from("hello ");
let str1 = "world!";
realstring.push_str(str1);
- add
&str
s usingformat!
let str1 = "hello ";
let str2 = "world!";
let message = format!("{}{}", str1, str2);
- a
char
is a different type than astr
orString
.char
always uses single quotes. - to get a
String
'schar
s you can callchars()
- you might find that instead of
chars()
you really wantas_bytes()
but if you aren't sure don't sweat it right now.
Example:
let name = String::from("ashley");
let letters = name.chars();
for l in letters {
// do something cool with characters
}
Macros are an interesting part of Rust. You know something is a macro if its name has
a !
. The least technical way to describe the cool thing about macros is that they
kinda get compiled twice. Don't worry if that doesn't make any sense.
println!
is the equivalent ofconsole.log
orputs
. It prints printable things to standard output, which is usually just the console.
println!("i get printed on the screen");
println!("hello {}!", "world");
format!
is also a macro. We talked about it before as a way to concatenatestr
s.
format!("my dogs are named: {} and {}", "cheeto", "frito");
pub fn say_hello(name: &str) -> String {
let message = format!("hello, {}!", name);
message
}
- put
pub
at the beginning if you want the function to be accessible outside the file as in a module or crate - the keyword
fn
is how we know it is a function - list parameters inside the parens in the style
parameter_name: Type
, separate by commas - use the
->
to say what type the function returns - return a value from the last line of a function by omitting the semicolon
- return early in a function using the
return
keyword
Rust has pattern matching and it's great!
match animal {
"cat" => "Meow",
"dog" => "Woof",
_ => "<indecipherable>", // trailing comma!
}
_
is used as a catch-all for anything that doesn't matchmatch
supports trailing commas, and it's best practice to use them :)
Rust doesn't have nil
/null
so if you want to express that something might return
something or nothing, you need to use the Option
type.
To write the Option
type, write the word Option
, followed by angle brackets with
a Type inside, e.g. Option<u32>
.
For example, if a parameter is optional you'd write:
fn greeting(name: Option<&str>) -> String {
let who = match name {
Some(n) => n,
None => "World",
};
format!("Hello, {}!", who)
}
greeting(Some("ashley"));
// "Hello, ashley!"
greeting(None);
// "Hello, World!"
Result
is kind of like Option
except instead of something or nothing, you
expect something that is Ok (Ok()
) or an error (Err()
).
To write the Result
type, write the word Result
, follow by angle brackets with
a Type and an Error Type inside, e.g. Result<u32, &'static str>
. For example:
fn parse_name(name: Option<&str>) -> Result<&str, &'static str> {
match name {
Some(n) => Ok(n),
None => Err("You must provide a name."),
}
}
Rust has unit testing built in! You can write tests in their own file or right inline with your code.
To designate a test write #[test]
above a code block with asserts:
fn say_hello(name: &str) -> String {
let who = match name {
Some(n) => n,
None => "World",
};
format!("Hello, {}!", who)
}
#[test]
fn it_should_say_hello() {
assert_eq!(say_hello(None), String::from("Hello, World!"));
assert_eq!(say_hello(Some("World")), String::from("Hello, World!"));
assert_eq!(say_hello(Some("ashley")), String::from(("Hello, ashley!"));
}
- The Rust Docs, https://doc.rust-lang.org/
- The Rust Book, https://doc.rust-lang.org/book/
into_rust
Screencasts, http://intorust.com/- The Rust Play Ground, https://play.rust-lang.org/
- Rust by Example, http://rustbyexample.com/
- Rust on exercism.io, http://exercism.io/languages/rust
- New Rustacean Podcast, http://www.newrustacean.com/