Rust-blog - Educational blog posts for Rust beginners

Last update: Jun 18, 2022

pretzelhammer's Rust blog 🦀

I write educational content for Rust beginners and Rust advanced beginners.

My posts are listed below in reverse chronological order.

Date Title Translations
2021-05-11 RESTful API in Sync & Async Rust
2021-03-31 Tour of Rust's Standard Library Traits 中文
2020-11-01 Learn Assembly with Entirely Too Many Brainfuck Compilers
2020-07-22 Sizedness in Rust
2020-05-19 Common Rust Lifetime Misconceptions русский · 日本語 · 中文
2020-05-09 Learning Rust in 2020
2020-05-02 Why blog?

Note: Translations are community-maintained.

Notifications

Get notified when a blog post get published by

Feedback

If you have any feedback please feel welcome to open an issue on this repo. I accept pull requests for minor fixes like typos and grammar.

Discuss

This repo has a discussion forum! Feel free to ask questions or start discussions.

Translations

If you wanna translate a blog post into another language that's awesome! Please feel free to fork this repo and promote your translation however you like. I also accept pull requests for translations if you'd like to host your translation on my blog directly.

Licensing

To be compatible with Rust, all code examples in this blog are licensed under Apache License Version 2.0 or MIT License, at your option.

I'd like to retain exclusive rights to the English version of the posts themselves, but as mentioned above if you translate a post into another language you're welcome to promote your translations however you like.

GitHub

https://github.com/pretzelhammer/rust-blog
Comments
  • 1. Remove static mut example

    In the blog post about lifetimes, the following code snippet is used:

    static BYTES: [u8; 3] = [1, 2, 3];
    static mut MUT_BYTES: [u8; 3] = [1, 2, 3];
    
    fn main() {
       MUT_BYTES[0] = 99; // compile error, mutating static is unsafe
    
        unsafe {
            MUT_BYTES[0] = 99;
            assert_eq!(99, MUT_BYTES[0]);
        }
    }
    

    There has been some controversy surrounding this feature (internals, blog), some even calling this a "misfeature" in dire need of replacement. Because they appear deceptively easy to use correctly (I think it's unproblematic here, given that indexing an array is a built-in, and not a call to index_mut which AFAIK is UB), perhaps at least a warning should be added that this is non-trivial.

    Reviewed by troublescooter at 2020-11-09 15:24
  • 2. My benchmark results

    I'm confused and wondering why are the results so different 🤔

    I'm using the latest nightly, which is 1.54.0 and node 16.0.0. All tests are just for "Read". So I tested the same code in master on my local machine, which is: Desktop Linux, i7 3GHz, 8 core (8 thread), 16GB memory 2667MHz

    SA
    
    Requests      [total, rate, throughput]         1060260, 17670.99, 17670.37
    Duration      [total, attack, wait]             1m0s, 1m0s, 2.106ms
    Latencies     [min, mean, 50, 90, 95, 99, max]  334.431µs, 2.219ms, 2.072ms, 2.965ms, 3.393ms, 5.35ms, 48.375ms
    Bytes In      [total, mean]                     202156240, 190.67
    Bytes Out     [total, mean]                     0, 0.00
    Success       [ratio]                           100.00%
    Status Codes  [code:count]                      200:1060260
    
    DR
    
    LATEST THROUGHPUT INFO
    Requests      [total, rate, throughput]         588250, 9804.16, 9803.81
    Duration      [total, attack, wait]             1m0s, 1m0s, 2.135ms
    Latencies     [min, mean, 50, 90, 95, 99, max]  373.671µs, 3.867ms, 3.614ms, 5.928ms, 6.807ms, 8.765ms, 31.832ms
    Bytes In      [total, mean]                     112159696, 190.67
    Bytes Out     [total, mean]                     0, 0.00
    Success       [ratio]                           100.00%
    Status Codes  [code:count]                      200:588250 
    
    PEM
    
    LATEST THROUGHPUT INFO
    Requests      [total, rate, throughput]         650226, 10837.10, 10836.52
    Duration      [total, attack, wait]             1m0s, 1m0s, 3.258ms
    Latencies     [min, mean, 50, 90, 95, 99, max]  421.593µs, 3.662ms, 3.206ms, 6.278ms, 7.571ms, 10.887ms, 135.706ms
    Bytes In      [total, mean]                     124626650, 191.67
    Bytes Out     [total, mean]                     0, 0.00
    Success       [ratio]                           100.00%
    Status Codes  [code:count]                      200:650226  
    

    I ran it also on another machine, Laptop Linux, i9 2.4GHz, 8 core (16 thread), 32GB memory 3200MHz, and faced completely different result:

    SA
    
    LATEST THROUGHPUT INFO
    Requests      [total, rate, throughput]         1101823, 18363.66, 18363.24
    Duration      [total, attack, wait]             1m0s, 1m0s, 1.366ms
    Latencies     [min, mean, 50, 90, 95, 99, max]  365.511µs, 2.101ms, 1.935ms, 2.995ms, 3.492ms, 4.689ms, 43.751ms
    Bytes In      [total, mean]                     210080948, 190.67
    Bytes Out     [total, mean]                     0, 0.00
    Success       [ratio]                           100.00%
    Status Codes  [code:count]                      200:1101823
    
    DR
    
    LATEST THROUGHPUT INFO
    Requests      [total, rate, throughput]         218746, 3645.42, 3645.34
    Duration      [total, attack, wait]             1m0s, 1m0s, 1.195ms
    Latencies     [min, mean, 50, 90, 95, 99, max]  536.327µs, 10.683ms, 10.52ms, 20.746ms, 24.02ms, 29.712ms, 136.249ms
    Bytes In      [total, mean]                     41707600, 190.67
    Bytes Out     [total, mean]                     0, 0.00
    Success       [ratio]                           100.00%
    Status Codes  [code:count]                      200:218746
    
    PEM
    
    LATEST THROUGHPUT INFO
    Requests      [total, rate, throughput]         656688, 10944.79, 10944.22
    Duration      [total, attack, wait]             1m0s, 1m0s, 3.115ms
    Latencies     [min, mean, 50, 90, 95, 99, max]  553.575µs, 3.541ms, 3.302ms, 5.437ms, 6.413ms, 9.094ms, 162.15ms
    Bytes In      [total, mean]                     125865200, 191.67
    Bytes Out     [total, mean]                     0, 0.00
    Success       [ratio]                           100.00%
    Status Codes  [code:count]                      200:656688
    

    Now I have two questions: 1- Why is it completely different from what we have here in the blog post? 2- Why DR is so much different on these two machines?! (I ran them several times, it's almost the same)

    Reviewed by omid at 2021-05-13 20:49
  • 3. Mention that Read & Write aren't in the prelude when talking about Generic blanket impls

    First off, amazing article! Thanks so much for writing it, it looks like a great reference and I've learnt way more than I probabaly need to know 😅.

    In the Read & Write section you mention the Generic blanket impls. You already mention this in the Scope section, but I think it's worth reiterating that Read & Write aren't in the prelude so if you want to use these blanket impls you need to bring them into scope. I think it's a common enough gottcha that a lot of people would be thankfull to be reminded.

    Reviewed by Akeboshiwind at 2021-04-24 14:05
  • 4. subjective issue, idk what title to give

    Hey, I just started reading the too many brainfuck compilers article and it is very interesting, however, I immediately noticed a code smell I would instantly refactor - it is subjective and I may be wrong by making a whole issue about it, but here it is:

    So you have a code that looks like:

    pub enum Inst {
        IncPtr(usize),
        DecPtr(usize),
        IncByte(usize),
        DecByte(usize),
        WriteByte(usize),
        ReadByte(usize),
        LoopStart(usize, usize),
        LoopEnd(usize, usize),
    }
    

    Then you spend extra 3 lines of the article ~~documenting~~ explaining what are these usizes for, but this can be easily made into a self-documented and much more readable code (and at places where you use it too). For example (with compact formatting here in the issue):

    pub enum Inst {
        IncPtr { by: usize },
        DecPtr { by: usize },
        IncByte { by: usize },
        DecByte { by: usize },
        WriteByte { times: usize },
        ReadByte { times: usize },
        LoopStart { times: usize, end_idx: usize },
        LoopEnd { times: usize, start_idx: usize },
    }
    

    The run-length encoding is way too repetitive and by definition is in each enum variant, so it can be abstracted away in a struct:

    pub struct Inst {
        pub kind: InstKind,
        pub times: usize,
    }
    
    pub enum InstKind {
        IncPtr,
        DecPtr,
        IncByte,
        DecByte,
        WriteByte,
        ReadByte,
        LoopStart { end_idx: usize },
        LoopEnd { start_idx: usize },
    }
    

    This improves readability and usability by a lot with no downsides (not like there is or will be 7 layers of structs/enums), and I honestly don't really know why tuple structs even exist at all. As I've said, this is subjective, feel free to ignore this, it just immediately tingled me when I was reading your article (didn't even read past this yet, but it seems very-very interesting).

    Reviewed by necauqua at 2020-11-11 22:07
  • 5. Clarify a license for blog posts themselves

    Quite self-explanatory title. I want to translate one of your blog posts and publish it on a IT platform, namely habr.com, however, I am not sure if I am allowed to do so. Here are the relevant parts of Habr user agreement at the moment (emphasis mine):

    4.8. By accepting the terms and conditions of this Agreement, the User shall provide Habr with a free (non-exclusive) license for using the Content in the following ways:

    <...>

    • to distribute copies of the Content, i.e. to provide access to material reproduced in any material form, including through network and otherwise, as well as by selling, renting, leasing, lending, including importation for any of these purposes (right of distribution);

    <...>

    • right to assign all or part of the received rights to third parties (the right to sublicense).

    <...> 4.11. The User guarantees the right to use the Content under the terms and conditions of the aforementioned license to the extend required.

    Since you didn't specify a license for posts themselves, you still have the exclusive rights for all your content, thereby I can't even legally publish a translation, not only on Habr but anywhere.

    Reviewed by AnthonyMikh at 2020-07-11 21:47
  • 6. Question about leaking with static refs

    I'm trying to understand how leaking works in one of the &'static examples.

    It's possible to generate random dynamically allocated data at run-time and return 'static references to it at the cost of leaking memory.

    use rand;
    
    // generate random 'static str refs at run-time
    fn rand_str_generator() -> &'static str {
        let rand_string = rand::random::<u64>().to_string();
        Box::leak(rand_string.into_boxed_str())
    }
    

    Part of my confusion comes from the Box::leak method. The documentation says that it returns a reference to the boxed value. If a reference is returned, that means the data is still there and the program hasn't "forgotten" about it. Maybe I'm misunderstanding what it means to "leak" memory. Can you help me understand?

    Reviewed by zmitchell at 2020-05-22 17:34
  • 7. 9) downgrading mut refs to shared refs is safe: last example seems confusing

    In 9) downgrading mut refs to shared refs is safe the last example starts with a block commented with // drop the returned mut Player refs since we can't use them together anyway. Commenting out this block still allows the code to compile (playground), and its purpose is unclear to me. I think it might be better to just remove it?

    Reviewed by BartMassey at 2020-05-20 08:04
  • 8. Fix sizedness post typos

    Hello! First and foremost, I loved this post!! It's probably the best explanation on "sizedness" for Rust there is 😊

    So reading it, I've found a couple of typos, here's the fix!

    Reviewed by evaporei at 2021-06-02 01:27
  • 9. Chinese Translation Completed: Tour of Rust's Standard Library Traits

    I am working on translating this article into Chinese.

    This is a semi-finished article.

    This article is so long that I need a lot of time.

    I hope other people know about my work to avoid repeated translations.

    Reviewed by skanfd at 2021-04-18 16:49
  • 10. PartialEq example isn't right

    The "Kelvin / Celcius / Fahrenheit" example for PartialEq isn't right, as floating point numbers suck.

    I expected to break transitivity, but it turns out even symmetry is broken fairly easily, see for example:

    https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=754a08485eb182e995f3e9889243dd81

    To fix, while much less fun, maybe do millimeters, centimeters, kilometers? If they are each stored as i32, you could make the millimeters in i64 for comparison, which deals with overflow.

    Reviewed by ChrisJefferson at 2021-04-07 11:54
  • 11. Confuse: lifetime with struct and self.

    https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md

    #[derive(Debug)]
    struct NumRef<'a>(&'a i32);
    
    impl<'a> NumRef<'a> {
        // no more 'a on mut self
        fn some_method(&mut self) {}
    
        // above line desugars to
        fn some_method_desugared<'b>(&'b mut self){}
    }
    
    fn main() {
        let mut num_ref = NumRef(&5);
        num_ref.some_method();
        num_ref.some_method(); // compiles
        println!("{:?}", num_ref); // compiles
    }
    

    It seems you simply give the solution (let compiler handle the lifetime). but why? what the lifetime 'a in struct NumRef doing/restricting? what is lifetime 'a in fn main ? (desugar lifetime in fn main maybe helpful?)

    Thanks.

    Reviewed by towry at 2020-11-26 00:55
  • 12. Misconception discussion: T is a superset of both &T and &mut T

    While it's true and can be presented with generics, maybe a note that the following is possible would be beneficial, so nobody erroneously extrapolates the rule:

    struct Foo();
    trait Trait {}
    impl Trait for Foo {}
    impl Trait for &Foo {}
    impl Trait for &mut Foo {}
    

    Like with impl Read for TcpStream and impl Read for &TcpStream.

    Reviewed by wodny at 2022-05-13 10:53
  • 13. Fix a typo for JA translation

    Follow up #17.

    This PR fixes a typo of the following translation from EN to JA.

    try not to re-borrow mut refs as shared refs, or you're gonna have a bad time

    https://github.com/pretzelhammer/rust-blog/blob/28ad3b0/posts/common-rust-lifetime-misconceptions.md

    The current translation seems to be missing "not".

    Reviewed by koic at 2022-04-03 12:19
  • 14. Customer review for Rust on the eve of 2022

    I would want to read your "customer's review" after 1 and half years later you started blogging about Rust.

    Questions to be answered in the article from my point of view:

    • So far, how was your Rust journey?
    • Is the Rust ecosystem overperformed, underperformed, or average in terms of growth when you compare with your expectations a year ago?
    • Do you think that Rust adoption is increasing and Rust employee is on the demand?
    • What's the biggest disappointment? e.g. Some of the advanced Rust developers think that the requirement of unsafe becomes a disappointment since the sales pitch was about safety.
    • Do you remember a good problem exists in other languages that you use but not in Rust?
    • What is missing for now where you use Rust?

    PS: I've met with your blog through Learning Rust in 2020 while I was looking for upper-beginner content in Rust. The article is great but some parts might be outdated as there are updates on mentioned platforms.

    Reviewed by mtunad at 2021-12-06 19:10
  • 15. `asymmetry` requirements in `PartialOrd`

    In the blog post tour of rust standard library traits, I feel the paragraph of asymmetry requirements in partial_cmp is not right:

    All PartialOrd impls must ensure that comparisons are asymmetric and transitive. That means for all a, b, and c:

    • a < b implies !(a > b) (asymmetry)
    • a < b && b < c implies a < c (transitivity)

    In the document for PartialOrd, there is no part about asymmetry. The requirements for partial_cmp is:

    The comparison must satisfy, for all a, b and c:

    • transitivity: a < b and b < c implies a < c. The same must hold for both == and >.
    • duality: a < b if and only if b > a.

    Maybe the document is updated and we should catch up?

    Reviewed by VitalyAnkh at 2021-10-22 18:08
  • 16. Request for additional example in closure/function lifetime elision distinction

    From here: https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md#10-closures-follow-the-same-lifetime-elision-rules-as-functions

    There's no good reason for this discrepancy. Closures were first implemented with different type inference semantics than functions and now we're stuck with it forever because to unify them at this point would be a breaking change.

    Would it be a breaking change? I'm struggling to come up with a example of a closure that currently compiles that would no longer compile if the elision rules were changed to match functions. A one-line example of such a closure would be illustrative and unobtrusive here. And in the event that the claim is mistaken, that would bode well for changing the language to remove this discrepancy.

    Reviewed by bstrie at 2021-07-19 15:55
Blog posts, mostly about Rust.

Sean Chen's Blog ?? Blog posts, mostly about Rust. Posts Date Title 2021-04-06 A Beginner's Guide to Handling Errors in Rust 2021-01-23 Implementing a

Apr 9, 2022
A Matrix bot which can generate "This Week in X" like blog posts
A Matrix bot which can generate

hebbot A Matrix bot which can help to generate periodic / recurrent summary blog posts (also known as "This Week in X"). The bot was inspired by twim-

May 30, 2022
This blog provides detailed status updates and useful information about Theseus OS and its development

The Theseus OS Blog This blog provides detailed status updates and useful information about Theseus OS and its development. Attribution This blog was

Apr 14, 2022
Leetcode Solutions in Rust, Advent of Code Solutions in Rust and more

RUST GYM Rust Solutions Leetcode Solutions in Rust AdventOfCode Solutions in Rust This project demostrates how to create Data Structures and to implem

Jun 25, 2022
Simple autoclicker written in Rust, to learn the Rust language.

RClicker is an autoclicker written in Rust, written to learn more about the Rust programming language. RClicker was was written by me to learn more ab

Mar 1, 2022
Rust programs written entirely in Rust

mustang Programs written entirely in Rust Mustang is a system for building programs built entirely in Rust, meaning they do not depend on any part of

Jun 23, 2022
Rust 核心库和标准库的源码级中文翻译,可作为 IDE 工具的智能提示 (Rust core library and standard library translation. can be used as IntelliSense for IDE tools)

Rust 标准库中文版 这是翻译 Rust 库 的地方, 相关源代码来自于 https://github.com/rust-lang/rust。 如果您不会说英语,那么拥有使用中文的文档至关重要,即使您会说英语,使用母语也仍然能让您感到愉快。Rust 标准库是高质量的,不管是新手还是老手,都可以从中

Jun 26, 2022
A library for extracting #[no_mangle] pub extern "C" functions (https://docs.rust-embedded.org/book/interoperability/rust-with-c.html#no_mangle)

A library for extracting #[no_mangle] pub extern "C" functions In order to expose a function with C binary interface for interoperability with other p

Feb 17, 2022
clone of grep cli written in Rust. From Chapter 12 of the Rust Programming Language book

minigrep is a clone of the grep cli in rust Minigrep will find a query string in a file. To test it out, clone the project and run cargo run body poem

Dec 14, 2021
The ray tracer challenge in rust - Repository to follow my development of "The Raytracer Challenge" book by Jamis Buck in the language Rust
The ray tracer challenge in rust - Repository to follow my development of

The Ray Tracer Challenge This repository contains all the code written, while step by implementing Ray Tracer, based on the book "The Ray Tracer Chall

Jun 13, 2022
Learn-rust-the-hard-way - "Learn C The Hard Way" by Zed Shaw Converted to Rust

Learn Rust The Hard Way This is an implementation of Zed Shaw's Learn X The Hard Way for the Rust Programming Language. Installing Rust TODO: Instruct

Jun 15, 2022
Learn to write Rust procedural macros [Rust Latam conference, Montevideo Uruguay, March 2019]
Learn to write Rust procedural macros [Rust Latam conference, Montevideo Uruguay, March 2019]

Rust Latam: procedural macros workshop This repo contains a selection of projects designed to learn to write Rust procedural macros — Rust code that g

Jun 24, 2022
The Rust Compiler Collection is a collection of compilers for various languages, written with The Rust Programming Language.

rcc The Rust Compiler Collection is a collection of compilers for various languages, written with The Rust Programming Language. Compilers Language Co

Jan 17, 2022
Integra8 rust integration test framework Rust with a focus on productivity, extensibility, and speed.

integra8 Integra8 rust integration test framework Rust with a focus on productivity, extensibility, and speed. | This repo is in a "work in progress"

Jan 15, 2022
Neofetch but in Rust (rust-toml-fetch)
Neofetch but in Rust (rust-toml-fetch)

rtfetch Configuration Recompile each time you change the config file logo = "arch.logo" # in src/assets. info = [ "", "", "<yellow>{host_n

Jun 6, 2022
Rust Sandbox [code for 15 concepts of Rust language]

Rust-Programming-Tutorial Rust Sandbox [code for 15 concepts of Rust language]. The first time I've been introduced to Rust was on January 2022, you m

May 22, 2022
TypeRust - simple Rust playground where you can build or run your Rust code and share it with others

Rust playground Welcome to TypeRust! This is a simple Rust playground where you can build or run your Rust code and share it with others. There are a

Jun 17, 2022
The Computer Language Benchmarks Game: Rust implementations

The Computer Language Benchmarks Game: Rust implementations This is the version I propose to the The Computer Language Benchmarks Game. For regex-dna,

Apr 13, 2022
Rust explained using easy English
Rust explained using easy English

Update 22 December 2020: mdBook can be found here. 28 November 2020: Now also available in simplified Chinese thanks to kumakichi! 1 February 2021: No

Jun 25, 2022