The best way to install Rust is with [rustup](https://www.rustup.rs/). 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
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
-
http://crates.io is like https://pursuit.haskell.org/ and https://hoogle.haskell.org/
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 integer -
i32
: signed 32-bit integer -
String
and/or&str
: more on these below -
bool
: a boolean
fn main() {
let a: f64 = 32;
println!("a = {}", a);
}
error[E0308]: mismatched types
--> src/main.rs:2:15
|
2 | let a: f64 = 32;
| --- ^^
| | |
| | expected `f64`, found integer
| | help: use a float literal: `32.0`
| expected due to this
For more information about this error, try `rustc --explain E0308`.
fn main() {
let a = 32;
println!("a = {}", a);
println!("Setting a to 33");
a = 33;
println!("a = {}", a);
}
This won’t compile in Rust.
error[E0384]: cannot assign twice to immutable variable `a`
--> src/main.rs:5:5
|
2 | let a = 32;
| -
| |
| first assignment to `a`
| help: consider making this binding mutable: `mut a`
...
5 | a = 33;
| ^^^^^^ cannot assign twice to immutable variable
For more information about this error, try `rustc --explain E0384`.
fn main() {
let mut a = 32;
println!("a = {}", a);
println!("Setting a to a + a^2");
a = {
let a_squared = a * a;
a + a_squared
};
println!("a = {}", a);
}
a = 32
Setting a to a + a^2
a = 1056
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. -
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
usingformat!
let str1 = "hello ";
let str2 = "world!";
let message = format!("{}{}", str1, str2);
Macros are an interesting part of Rust. You know something is a macro if its name has
a !
.
-
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");
pub fn say_hello(name: &str) -> String {
let message = format!("hello, {}!", name);
message
}
say_hello :: String -> String
say_hello name =
let message = "Hello, " <> name <> "!"
in message
pub fn say_hello<T: Display>(name: T) -> String {
let message = format!("hello, {}!", name);
message
}
say_hello :: forall t. Show t => T -> String
say_hello name =
let message = "Hello, " <> show name <> "!"
in message
-
use
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
#[derive(Debug)]
struct Rec {
foo: String,
bar: String
}
fn main() {
let obj = Rec {foo: String::from("foo"), bar: String::from("bar")};
println!("Record = {obj:?}");
}
Rust has pattern matching also
match animal {
"cat" => "Meow",
"dog" => "Woof",
_ => "<indecipherable>", // trailing comma!
}
Rust/Purescript/Haskell
doesn’t have nil
/null
so if you want to express that something might return
something or nothing, you need to use the Option/Maybe
type.
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/Either
is kind of like Option
except instead of something or nothing, you
expect something that is Ok (Ok()
) or an error (Err()
).
fn parse_name(name: Option<&str>) -> Result<&str, &'static str> {
match name {
Some(n) => Ok(n),
None => Err("You must provide a name."),
}
}
-
Reference types are written with an
&
:&i32
. -
References can be taken with
&
(like C/C++).
-
References can be dereferenced with
*
(like C/C++). -
References are guaranteed to be valid.
-
Validity is enforced through compile-time checks!
-
class Eq a where
eq :: a -> a -> Boolean
instance eqEither :: Eq t => Eq e => Eq (Either t e)
eq self other = case (self, other) of
(Right(t1), Right(t2)) -> eq(t1, t2)
(left(e1), left(e2)) -> eq(e1, e2)
_ => false