My Authors
Read all threads
My girlfriend went on holiday with her family, so I decided to use all my free time to learn Rust while she's away. To keep myself motivated, I'll document the experience here.

From #JavaScript / #Typescript to #rustlang: A thread
First, some context (1/4): I tried to learn rust years ago, when there was syntax for multiple types of pointers. I'm familiar with many of its concepts, but never took the time to do something useful with it.
Context (2/4): I've worked with multiple languages, but spent the last couple of years using js and ts.
Context (3/4): My goal is to be able to understand and maybe contribute to @sorpaas' EVM (github.com/sorpaas/rust-e…) before my gf returns, in about a week. I already work on an EVM implementation, so it should be doable.
Context (3/4): I mostly work on DevEx-related projects, so I may overanalyse this whole thing 😅
I was planning to read The Rust Programming Language, but it's too verbose. Definitely not my thing! It has a great foreword though. The empowerment thing really resonates with me.

doc.rust-lang.org/stable/book/fo…
I'll be following Rust By Example. Way more concise. Having most of the content in comments is cool. I can copy it into vscode and read and experiment from there.
Cargo seems great!! It's so fast, compared to npm. I know people complain about rustc being slow, so `cargo check` makes sense to me.

I haven't dealt with dependencies yet, I hope that's not as messy as on Node 🙏🏻
I'm a HUGE fan of @PrettierCode, so I can't be more happy with `cargo fmt` being included in the default installation.
@code support for rust looks good so far. I just installed whatever extension vscode suggested, and I'm not at all disappointed. It's not that fast, but I guess that's the language server's fault.

Does @jetbrains have plans for a Rust IDE?
Having a range operator is great, but two dots? WTF! Why? And `..=`? Come on!

`...` would have been much more natural. Is that another operator? Does Rust have something like js' spread operator?
I'm loving the trait system so far. I've only worked with fmt things, but they seems very well thought out and tidy.

I haven't made up my mind on how this compare to inheritance-based languages. I worked ~9 months with Go, and I don't remember missing classes there. We'll see.
Mixed feelings about `#[derive(Debug)]`: On one side, it's really practical, on the other one, it's too magical.

I hope that's a first-class construction. It doesn't seem to be a macro, as those are applied with `!`.
Struct update syntax is cool. Not that different from the js spread operator, except it uses two dots (again! wtf #rustlang people?) and you use it in the opposite order.

I guess the order makes sense, it emphasises the new values.
There's syntax for user-defined structs and tuples, and it's ok-ish.

I'd love to be able to do this `let point = { x: 10.3, y: 0.4 };` instead of `let point: Point = { x: 10.3, y: 0.4 };`. I wouldn't be saving a single keystroke though.
On the other hand, destructuring is a pleasure to work with. I don't know why, but it feels much clearer than in js.

It's almost the same syntax than literals, so maybe that's the reason for the limitation mentioned in the previous tweet.
I was scared that rust might force you to write things like this `let Point { x: x, y: y } = point;`, but it also accepts `let Point { x, y } = point;`!
Dead code warnings are super annoying when learning! I'm trying to disable them for my entire project, but I couldn't do it with ~3min of googling 😩
Ok, got it! You need two global "attributes" (what's an attribute?) in your main.rs:

#![allow(dead_code)]
#![allow(unused_variables)]

Thanks @snfernandez
Type safe println is amazing 🔥
IMO `try!(write!(f, "{}", value))` looks better than `write!(f, "{}", value)?` but I've only written like 100 lines of rust so far 🤷🏻‍♂️

You probably use `?` all the time in real programs, so idk.
First borrow checker problem 🎉

I have so many questions rn, but first, look at this error message! I love it 😍
So, I'm MOVING my rectangle into the rect_area function. That gives it exclusive accesss to it, I think, so `println!` can't access it. Right?

But what if it evaluated the arguments in order? Is evaluation order defined? I should google it, but I'm afraid to end up in a 🐇🕳
Also, println! is not a function, it's a macro 🤔 Maybe evaluation order is defined AFTER the macro is applied.

Macros being hard to debug is my biggest fear about rust. I hope I can see the result of expanding it somehow.
To keep progressing, I fixed it by making my function take an immutable reference. I'll get back to the macros thing in the future.

Do people pass arguments using & most of the time? I get why you'd do it, but I was expecting that to be automatic.
Someone answered me on IRC: yes, it's common to pass arguments with &. Thanks Alexendoo!
Someone told me I could use this to see at the macro expansion: crates.io/crates/cargo-e…

It took a while to install, and then it failed because I'm not on nightly. Do people use the nightly build of their compilers? 🤯
Is there an easy way to get the type of something in vscode?

Now I do `let i:i32 = smth` and read the error message 😅
My reaction to Rust enums:
Please someone tell me that you get used to String vs str 🙏🏻
Defining methods can be weird at first, but it looks very similar to go.

You create an `impl`ementation block and define functions that take self as their first argument.
BTW, I think methods and static fields are called associated items here. Reading this right now: doc.rust-lang.org/reference/item…
I thought there was no way to force people to use your constructors, but there is! I still haven't played with that, but there's hope 🙌🏻
There's no function overload! 🤯

I found this, but seems complicated: medium.com/@jreem/advance…
Being able to redeclare a variable in the same scope is wild!

Most linters from other languages will complain about shadowing, but it's common practice in #rustlang.
I keep reading about enums. They are neat. I guess most things are represented with them.

There's also C-like enums. Those just have "integer" values, and are defined in the same way as the fancy ones.
Tweeting about this resulted to be useful. Thanks to everyone answering my questions!
I wonder why the type of integer numeric literals is i32 by default.

I don't have enough experience outside of x86 and modern android and ios development, so I was expecting a language this new to default to i64, or maybe to the word size.

Any clue?
I thought methods should normally receive `self` as their first argument, but that "consumes" your value! If you do that, you are giving the method invocation the ownership of the value. Try defining one, and calling it twice in a row.

You probably want to use `&self`, right?
I don't know about you, but when learning a language, I normally do lots of small programs testing the edge cases of the language itself and my understanding about it.
A linked list is a box in a box in a box in a box in a box in a box in a box in a box in a box in a box in a box
A Box is a kind of pointer. Parts of Box are implemented in rust itself 🤯

I know there are other kinds of smart pointers, and also "raw pointers". Will get back to this soon, I guess.
This linked list I'm working with is interesting. The `prepend` method consumes it. You get loose access to your list, but get back a new one with an extra element. The new one reuses the old one, so it should be super fast.

doc.rust-lang.org/stable/rust-by…
This example declares the list as mut. Why not do something like this?

let list = List::new();
let list = list.prepend(1);
let list = list.prepend(2);
"matching on a concrete type `T` is preferred over a match on a reference `&T`" -- Thanks for the tip RBE, but why?!
Someone on IRC told me that it's explained here: doc.rust-lang.org/reference/expr…

I know very little about lifetimes, so I don't get it yet. I guess that's why the book doesn't explain it.
I'm not sure if I like that `return` is optional. Rust is an expression-oriented language, I get it, but IMO this is hard to read:
Apparently, a few versions ago you had to prepend a `&` to every match arm when matching a reference.
BTW, the #rust channel on freenode has been extremely useful so far
Rust has `const` and `static` keywords. I think this can be extremely confusing if you are coming from js, so I'll try to explain their difference here. (1/4)
When compiling, rustc emits a binary. When you want to execute that binary, a loader (another program) will copy it into memory and do some initialisation tasks. (2/4)
A binary has different sections. One of those contains the actual code (it's called .text), but another one (.data) has all the constant data that your program uses, like string literals. Both of these sections are copied verbatim into memory by the loader. (3/4)
`static` means "put this value in .data, I want it in memory".

`const` means "this is immutable, feel free to inline the value and save some memory".

When in doubt, you should probably use `const`. (4/4)
I have the impression that the rust community uses more computer science-y terms than others, like "variable bindings". Is it just me?
I tried to create a struct with a mutable i32 inside, and failed. This should probably be a Box 🤔This book doesn't explain lifetimes until chapter 15 😰
You can declare a variable and define its value later. This is pretty common in programming languages. But rust doesn't force you to declare its type, it'll infer it.

This works:

let v;
// ...
v = 1;
For contrast, if you do that in TS you get an `any`. In rust, you get i32.
This doesn't work
I thought that it would infer an union type, but I don't even know if they exist.

They probably don't, you have really powerful enums for that.
No implicit type conversions, that's good! Type coercion in js is a mess.

You know what they say: Rust wasn't built in 10 days.
Actually, I only wrote a single post in my personal blog, and it's about type coercion in js:

patriciopalladino.com/blog/2012/08/0…
Back to rust, you can cast things explicitly. It mostly follows C casting rules. No idea what those are, and I don't care right now.

They are definitely not just reinterpreting the memory as the new type.
I always feel like casting numbers requires too much knowledge about the language. I prefer to use a function that handles the different edge cases explicitly.
Rust's type inference is really powerful. I'd love to see how it compares to Typescript's, but don't wanna derail on that.

If TS were like Rust, the set here would be a `Set<number>`, instead of a `Set<unknown>`:

let m = new Set();
m.add(123);

Impressive!
If your types aren't CamelCased, you get a compilation warning. I like that.
`type T1 = T2` is just an alias, you can use `T1` and `T2` interchangeably. Nothing new here. You can encapsulate your data representation with other features.
Traits can be parametric, this is getting fun 😏
There's a trait called `From`. You implement it to create values of your types based on the values of another one. If you do that, you get `Into` for free, which does the opposite.
The next section is about `TryFrom` and `TryInto`, which are kind of the same. The difference is that these can fail.

I'm starting to see a pattern with "try" being used as "this thing may fail".
To implement `TryFrom` you have to provide a `try_from` function. As it can fail, it returns a `Result`. Rust has no exceptions, so errors are returned and handled "manually".
Result reminds me of Maybe from Haskell. Is Result a monad? I always forget its exact definition.
Oh, apparently you have to provide an error type. This example uses the unit tuple () type (is it called like that? 🤷🏻‍♂️).

I'd probably use an enum for that, so you can discern between errors.
I'm constantly frustrated about `catch (e)` being untyped in TS. I understand the reason for this, but it's still annoying. This Result thing has a lot of potentials.
I had the impression that `try!` and `?` had to be related to `Result`, so I tried using `?` on a `try_from` inside `main`. This error is incredibly juicy
Next thing I did was googling `std::opts::try`, and got into this doc.rust-lang.org/std/ops/trait.…

Everything has a message about it being "nightly-only". That's so confusing. Shouldn't the official docs point to the stable version?
I'd love to know how you prevent error types from leaking. If I'm using a function that returns some kind of Result, I may not want to return that, but my own Result.
Oh, and there's also `#[derive(PartialEq)]`, which also looks like black magic.
From PartialEq's doc: "Trait for equality comparisons which are partial equivalence relations" -- lol, what?😂

I know what that means, but I have a CS degree. This must be frustrating for many ppl.
Enough for today 🥱

It was very fun doing this. I'm moving slower, but I think I'm still on track with my goal.

See you tomorrow 👋🏻
Day number 2 💪🏻

I only have a couple of hours, so I won't be tweeting as much as yesterday.
I've got tons of answers and tips! 😍

I'll try to reply to all of them, but I may not be able to do it if I want to keep making progress.
Some highlights and learnings from those answers:
"String is your string, &str is a view into someone else's string."

Makes sense. I guess I'd be working mostly with String.
I can create my own derive magic!! 😈

Well, I have to learn about "procedural macros" first. Aren't all macros procedural? Can I hang the compiler with a macro?
Now that I think of, I've seen something like that for json (de)serialization using serde in @ParityTech's ethereum node.
Apparently, there was an "..." operator for ranges, but that was too error-prone (.. and ... look almost the same), so they removed it. Makes sense.

I think Ruby has .. and ...
Something really cool is that the language is designed on github. See github.com/rust-lang/rust…
There are parts of the language that aren't stable yet, and are still usable on stable. For example, `Try`.

You can use it through `?`, but you can't implement it because it is not finalized, and may change.

It's an interesting approach, just a little confusing for newcomers.
There's no clear consensus on how to handle errors, I think.

Someone recommended using different crates (libraries) for errors in applications vs libraries.

Never saw this idea before, but as errors are just values that you explicitly return, you can do that.
Number literals aren't always interpreted as i32. Rust's type inference is incredibly powerful 🤯
OMG @rustlang answered one of my tweets!
#[derive(Debug)] expansions use a library you can also use!
Rust evaluates arguments in left-to-right order.

I normally wouldn't care about this. I believe the evaluation order of args is undefined in most langs, but I think the borrow checker makes it relevant.
println is not a macro! I feel betrayed 😰
Note: I should try rust-analyzer and the rust plugin for intellij
There's no equivalent of TS' union types in rust. You can use enum for that 🤷🏻‍♂️
You can't have actual monads in Rust. I'll read more about that soon 🤔
TIL: higher kinded types

joshlf.com/post/2018/10/1…
There's a thing called "marker types" that let you impose a relative order on method calls. 😦

Are they related to typestates?
Boxes own their content, references don't
Back to the book now 📖

There are native assertion macros. That's interesting, but I bet people end up using libraries for that.
There a thing called "turbofish syntax" 😂

It's when you specify types like this `f::<i32>()`.

Most languages don't require the `::` for that. I guess omitting those would lead to some syntax ambiguity in rust.
You can use `_` as a type wildcard in some places, and let the compiler infer it.
More about `return` being optional:

If the last line of your function doesn't have a `;`, then, it's an expression, and it is used as the return value.

If you add a `;`, it's a statement, and a `()` is returned instead.

I saw this in another lang. Maybe rust many years ago?
I just found `unwrap`. I thought that it was just another syntax for `?`, but it isn't.

If an unwrap fails, it "panics". I guess a panic is an unrecoverable error that crashes your program, like in go.
The next chapter is about expressions vs statements, but I already explained most of it 😏

Did I mention that I'm a huge PL nerd? 🤓
No parens for if conditions ✅

You must ALWAYS use curly braces, like an adult.

`if`s are also expressions 🤩
cargo fmt doesn't work if you have syntax errors.

Or maybe it's the vscode integration?
If you are using an `if` with an `else if` as an expression, you need an `else`, or you get a type error.
`loop` is cute.

Not sure if it makes a huge difference, but it's cute anyway.
There are labeled breaks, like in Java.

I've never used that in Java, and worked with it for years.

Hope they aren't common in Rust.
This "loop with return value" is really neat and dangerous at the same time. You'd better be sure that your loop will get into the `break`.
Do people use FizzBuzz as an interview question IRL?
Iterators are a common thing in most languages, the main difference in Rust is that they can borrow or consume your collection.
I can't say I like the `&mut` before the literal in this example.

Couldn't that be automatic? 😥
Next chapter is about `match` 🥳

Matching on numbers is incredibly powerful. e.g. `13..=19 => println!("A teen")`

Can I do that with my own types? 🙏🏻
THAT ERROR MESSAGE 🤯😍
I think match braces are evaluated in order. If the order didn't matter, rust should prove that they don't overlap, and error if they do.
I find matching references a little confusing.

I know that `&` is automatically inserted sometimes, but that makes it even more confusing.

Also, there's `ref` and `&`?
Guards in `match` remind me of Haskell. Pattern matching in Haskell is great.
I think that if you use a guard, you need a wildcard match. Makes sense, guards are evaluated at runtime, so rustc can't prove much about them.

e.g. this doesn't compile:
That `@` symbol on matches 🤨

`=` would be confusing though.
`if let` is very handy. You'd quickly end up with very deeply nested matches without it.
Random question: can I implement a trait for other people's types? I'm pretty sure I can.

How is that scoped? Are those implementations global? Or should I import them to reuse them from other modules? I wish it's the latter.
`while let` doesn't look that useful 🙈

There's an example in the book, but I'm not convinced.
It's pretty late here. See you tomorrow 👋🏻
Missing some Tweet in this thread? You can try to force a refresh.

Enjoying this thread?

Keep Current with Patricio Palladino 👷‍♂️

Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!