Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn main() {

F#:

```
```fs
let x =
let x = 5
let y = 10
Expand Down Expand Up @@ -105,15 +105,15 @@ 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;
```

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
```
Expand Down Expand Up @@ -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);
Expand All @@ -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();
Expand Down Expand Up @@ -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<T> {
head: Vec<T>, // A vec but we'll make sure it never has more than one item
Expand Down Expand Up @@ -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;

Expand All @@ -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;
```

Expand Down Expand Up @@ -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 {}

Expand Down Expand Up @@ -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];

Expand All @@ -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 =
Expand All @@ -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<String>,
population: u32
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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
Expand Down