diff --git a/README.md b/README.md index c1e854d..7408054 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ fn main() { F#: -``` +```fs let x = let x = 5 let y = 10 @@ -105,7 +105,7 @@ Both Rust and F# use postfixes on numbers to indicate the type if you want to ch And both Rust and F# have the option of putting _ in between numbers to make them readable. This code works in both languages: -``` +```fs let num = 8000000; let readableNum = 8_000_000; let maybeReadableNum = 8___________000________000; @@ -113,7 +113,7 @@ let maybeReadableNum = 8___________000________000; As for the F# `decimal` type (`Decimal` in .NET), Rust doesn't have one. Or rather, [it does](https://crates.io/crates/rust_decimal) but it's not part of the standard library. The Rust standard library is particularly small (doesn't even have a random number function for example) and decimals are another type for which external crates (crate = NuGet package, basically) are used. Adding an external crate to your Rust code is as simple as adding a single line to your `cargo.toml` file: -``` +```toml [dependencies] rust_decimal = "1.14" <-- Add this and you're done ``` @@ -1402,7 +1402,7 @@ fn main() { But the moment you push something into the `Vec` it will know the type. So this will work: -``` +```rust fn main() { let mut x = vec![]; x.push(9); @@ -1417,7 +1417,7 @@ Some of the most common are: `with_capacity`: every Vec has an automatically determined capacity that starts at 0, then goes to 4 and thereafter doubles whenever necessary. You can see this in action in the following code, which tracks the capacity of the `Vec` and prints whenever it doubles: -``` +```rust fn main() { let mut new_vec = vec![]; let mut current_capacity = new_vec.capacity(); @@ -1522,7 +1522,7 @@ Because they are composed of a head and a tail, F#ers love to put them into recu For Rustaceans, I think this type here I put together is probably similar to how a list looks in F# -``` +```rust #[derive(Debug)] struct FSharpList { head: Vec, // A vec but we'll make sure it never has more than one item @@ -1717,7 +1717,7 @@ There's no point to this `Book` struct except as an example of the easiest way t Traits in Rust refer to common functionality that you can implement on your own types. A trait is basically a group of shared methods under a name, and with this name you can guarantee to the compiler in a generic function that the object being passed in will be able to perform the behaviour you want it to. For example, maybe you have a `struct City` and would like to add one `City` to another. Since there is no way for the compiler to know how to do this, you `implement Add` for your `City` type. Then you look at the `Add` [trait documentation](https://doc.rust-lang.org/std/ops/trait.Add.html) and see if there's anything you need to do. If you see a "Required Methods" on the top right, it means that you need to write the function out yourself. Add has `fn add` up there with the following example of implementation: -``` +```rust impl Add for Point { type Output = Self; @@ -1732,7 +1732,7 @@ impl Add for Point { This trait has an `associated type`: the type that goes with it. You can see it on the line here: -``` +```rust type Output = Self; ``` @@ -1861,14 +1861,14 @@ Holding the mouse over `metropolis` shows `val metropolis : Metropolis`, and `pr While similar in this case, traits in Rust are quite different. Here's one more example of how they can be used, as trait bounds: -``` +```rust trait Duckish {} // For duck-like things trait Doggish {} // For dog-like things ``` We'll say that only duck-like things will implement Duckish, and dog-like things get Doggish. That's because we're going to make a `fn bark` and `fn quack` and don't want to let the wrong animal types use them. Note that the traits don't have any methods, but that's fine because they are just being used as bounds. The whole thing looks like this: -``` +```rust trait Duckish {} trait Doggish {} @@ -1914,7 +1914,7 @@ For the curious, [here are the methods for iterators in Rust](https://doc.rust-l Let's do some simple mapping in both languages. We'll make a Vec / List of three numbers that we'll double. -``` +```rust fn main() { let num_vec = vec![7, 8, 9]; @@ -1935,7 +1935,7 @@ This prints `[14, 16, 18]`, no surprise. Note the following: The F# code is simpler: -``` +```fs let listOne = [7..9] let listTwo = @@ -1951,7 +1951,7 @@ Now the big difference is that the Rust iterator methods work on anything that i Let's implement `Iterator` for a Metropolis type again. Each metropolis is composed of multiple cities, and our Metropolis iterator will return their names (if any). It'll look like this: -``` +```rust struct Metropolis { cities: Vec, population: u32 @@ -1994,7 +1994,7 @@ Helsinki Fold is interesting. It can be used for more interesting things than adding everything together, but let's stick to the simple examples for now. Here's a simple fold in Rust: -``` +```rust fn main() { let sum = (1..=10) .fold(0, |first_number, next_number| first_number + next_number); @@ -2005,7 +2005,7 @@ fn main() { Fsharpers will notice that the order is reversed: you start with the beginning value (here a 0), then name the variables, and then give instructions for what to do with them. -``` +```fs let sum = [1..10] |> List.fold (fun firstNumber secondNumber -> firstNumber + secondNumber) 0 @@ -2017,7 +2017,7 @@ So for the Rustaceans, you do this: start with `List.fold`, then do the regular But here's the interesting part. You can also write it like this: -``` +```fs let sum = [1..10] |> List.fold (+) 0