This is easy and it works! But the implementation is very specific to our struct.
The rest of the codebase doesn't really know that this type can be converted to a String and therefore you cannot build abstractions on top of this... π€¨
In fact, note how we needed to explicitly call `to_string()` in our `println!()` call.
If we try to remove that and pass the `creds` instance we get an error:
"`Credentials` cannot be formatted with the default formatter" π€·ββοΈ
Wouldn't it be nice if we could make this work? π€
The error itself is quite insightful. It is saying that we can make this work if we implement a specific trait for our `Credentials` struct.
In Rust, exposing certain behaviors is done by implementing specific traits. Regarding "to string" there are, in fact, a few options!
3 options (that I know about) are:
1. the std::fmt::Debug Trait 2. the std::string::ToString Trait 3. the std::fmt::Display Trait (the one recommended by our error)
Let's start with the Debug trait. The documentation says "Debug should format the output in a programmer-facing, debugging context".
This is a great way to provide details about a struct that should be visible only to developers.
Implementing the Debug trait manually is something that you rarely have to do manually. For the majority of use cases, the Derive macro will serve you well!
It is interesting to note that implementing the Debug trait manually requires you to use a `Formatter`. π€
From the docs: "A Formatter represents various options related to formatting. Users do not construct Formatters directly; a mutable reference to one is passed to the fmt method of all formatting traits, like Debug and Display."
Let's now talk about the std::string::ToString trait, which is defined as:
"A trait for converting a value to a String"
But the documentation also says it shouldnβt be implemented directly. `Display` should be implemented instead & you get the ToString implementation for free!
Implementing ToString for a struct will force you to have a `to_string()` method, but the common way to tell that an object can be converted to a string is the more generic `Display` trait. We can practically ignore the `ToString` trait at this point and focus only on Display!
"Display is similar to Debug, but Display is for user-facing output, and so cannot be derived".
The documentation is essentially saying that Display allows us to provide a user-facing description of a struct and that we can only implement the trait directly, no magic derive! π
Let's implement Display for our Credentials struct then...
Note that, again, we have to deal with a formatter.
A small productivity tip is that you can use the `write!` macro with formatters and convert:
```
f.write_str(self.api_key.as_ref())
```
to
```
write!(f, "{}", self.api_key)
```
Nicer (and more flexible), isn't it? π
Also, remember that the placeholder to use the Display trait is just `{}` (as opposed to `{:?}` or `{:#?}` for the Debug trait).
π So, just to summarise:
- `Debug` allows you to generate debug strings. It can be automatically derived.
- `Display` is the equivalent but for user-facing information. It CANNOT be derived.
- `ToString`... don't implement it, you get it for free with `Display`!
π
That's all I know about stringifying things in Rust! π
I hope this was interesting and I am curious to know if you learned something new or if all these things were already done and dusted in your Rust journey!
Did I miss or misunderstood something? plz, let me know! β€οΈ
If you'd like to see more of my #Rust#learning journey check out my #twitch channel, where I stream every week (Monday 5PM GMT) with @gbinside and @88_eugen our attempts at cracking the #AdventOfCode challenges using Rust!
1οΈβ£Β You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.
2οΈβ£ Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.
Software engineering #anxiety, let's talk about it. Specifically, let me try to deconstruct my personal anxiety
π§΅π
1οΈβ£ classic impostor syndrome: it doesn't matter how good I actually am with some technology/tool/technique. Even if I can get the job done, it still feels far from adequate and I feel like I have to rush to get better to defend my job title & credibility...
2οΈβ£ future tech gamble: tech is always changing and I need to be ready for the next big thing if I want to stay relevant in the market. But what is the next big thing? I don't know, of course, so I try to check out as many things as I can and often end up feeling overwhelmed! π€―
I spoke about how #JavaScript module bundlers (those things like #Webpack) work under the hood yesterday at @coderful!
πHere's a short-ish summary:
1/
TLDR: Module bundlers like Webpack are not "complicated" or "magic" per se, the practice of module bundling is a complicated matter and you need to understand it before you can fully understand what a module bundler does and how to configure it correctly! π¦
2/
Why do we need module bundlers? Several reasons:
- Today we rely a lot on third-party software (e.g. modules from #npm)
- There are many different standards for JavaScript modules
- We want to write code in a way that is convenient and just "compile" it for the browser
3/