"The two areas where it’s not yet a good fit are web frontends (though you can try) and native macOS apps." Could you please elaborate?
At Oxide, we named the company after Rust, but we use TypeScript on the frontend, not Rust. Rust is our default technology choice for most new code, but TypeScript is for frontend code. Rust on web frontends is just not super mature. You can do things with it, and it's very cool, but TypeScript is a very mature technology at this point, and gives a lot of similar benefits to Rust. And it can live natively in a browse…
Two Years of Rust
51–60 of 69 posts
Re: Two Years of Rust
#52Earlier quoted context omitted.
At Oxide, we named the company after Rust, but we use TypeScript on the frontend, not Rust. Rust is our default technology choice for most new code, but TypeScript is for frontend code. Rust on web frontends is just not super mature. You can do things with it, and it's very cool, but TypeScript is a very mature technology at this point, and gives a lot of similar benefits to Rust. And it can live natively in a browse…
love to hear from Oxide folk :) y'all do great stuff and great write-ups.
Re: Two Years of Rust
#53Earlier quoted context omitted.
I feel in rust you want to be a lot more judicious in where you introduce and deal with traits than in other languages with interfaces. Author blames lifetimes for this but I think the truth is that it is because there is no garbage collector so not everything is a fat pointer and fat pointers cannot have generic methods anyways because generic methods are monomorphized so they feel a bit lame even if you would reach…
Here's how I currently am doing it: I use the repository pattern. I use a trait: pub trait LibraryRepository: Send + Sync + 'static { async fn create_supplier( &self, request: supplier::CreateRequest, ) -> Result ; I am splitting things "vertically" (aka by feature) rather than "horizontally" (aka by layer). So "library" is a feature of my app, and "suppliers" are a concept within that feature. This call ultimately t…
Inject a short lived bee into your example. A database that is only going to live for a finite time.
Re: Two Years of Rust
#54Please don't take this the wrong way, it's just the editor in me. There's a typo at the end of the Error Handling section: When you need to explicitly handle an error, you omit the question mark operator and use thw Result value directly.
Re: Two Years of Rust
#55The mock example looked pointless. IO can’t be unit tested hence why you mock it. But his code didn’t do anything but confirm his mock worked. He’s writing mocks and testing mocks. The functionality he referenced is just inherently not unit testable. Again, If you try to mock it and test things you end up testing your mocked code. That’s it. I’ve seen this strange testing philosophy pop up time and time again where t…
It's an example for a blog post. I can't write thousands of lines of code for it, so I just sketched a vague outline.
Re: Two Years of Rust
#56Earlier quoted context omitted.
?ing Errors and never actually handling them is just a terrible practice. In fact it is just as bad as not doing error checking at all. Misusing a mechanism is not a point against the language. What makes this error checking good is that you can use it correctly and it is less cumbersome than the try/catch from C++. >Come on, let's be a bit more honest with ourselves about Result and '?' - it's not a full solution to…
> ?ing Errors and never actually handling them is just a terrible practice. This isn't true. It really depends. fn main() -> anyhow::Result { can be perfectly good, depending on your needs. What Rust does with error handling is give you flexibility. It's true that means you can make a mess. I myself have a TODO on my current codebase where I'm not exactly happy with what I'm doing at the moment overall. But it can al…
This gives the error to the calling process though. In some sense that means it is handled.
I don't think I disagree though, but I think my point still stands. If you do not think about at what point your errors are actually resolved then your program does not have proper error handling. If you unwrap in the middle of your code, you have to accept that crashing there is a possibility, even from an error far away.
Re: Two Years of Rust
#57Earlier quoted context omitted.
Here's how I currently am doing it: I use the repository pattern. I use a trait: pub trait LibraryRepository: Send + Sync + 'static { async fn create_supplier( &self, request: supplier::CreateRequest, ) -> Result ; I am splitting things "vertically" (aka by feature) rather than "horizontally" (aka by layer). So "library" is a feature of my app, and "suppliers" are a concept within that feature. This call ultimately t…
You've dodged the meat of my complaint by not having an example where you need to inject into a struct to test an implementation. Moreover, if you slap `Send + Sync + 'static` then you can certainly avoid the problems I am hinting at: you've committed to never having a lifetime and won't have to deal with the borrow checker. Inject a short lived bee into your example. A database that is only going to live for a finit…
Sure. "Dr, it hurts... well stop doing that." Sometimes, you can design around the issue. I don't claim that this specific pattern works for everything, just that this is how my real-world application is built.
> Moreover, if you slap `Send + Sync + 'static` then you can certainly avoid the problems I am hinting at: you've committed to never having a lifetime and won't have to deal with the borrow checker.
Yes. Sometimes, one atomic increment on startup is worth not making your code more complex.
> A database that is only going to live for a finite time.
This is just not the case for a web application.
Re: Two Years of Rust
#58Earlier quoted context omitted.
I really wish there was more of a discussion on Nim.
I've never looked closely at Nim because I think I don't need another fast GC language in addition to Go. What's your pitch for someone like me?
Re: Two Years of Rust
#59Earlier quoted context omitted.
> ?ing Errors and never actually handling them is just a terrible practice. I agree, but that's kind of my point - that's all these Rust praise articles are ever showing :). > But it is meaningless to talk about this without doing comparisons. Not comparing to other languages/approaches however allows a discussion to stay about Rust and how to make things better instead of yet another fruitless discussion about which…
>I agree, but that's kind of my point - that's all these Rust praise articles are ever showing :). Then they are completely misrepresenting what error handling is about. Rusts error handling is good because programs only crash where you allow them to crash. If you are using the error handling correctly, you only crash wherever there is an error you believe should be unrecoverable. >Not comparing to other languages/ap…
That's fine, but the commenter didn't pull this out of nowhere. It's in the article. Your reply makes it sound like you didn't read it, as if OP is giving a rare hypothetical that most Rust programmers don't support. This is common error handling advice in the Rust community.
And this is representative of what you may run into when reading other people's code or trying to contribute to their library.
Re: Two Years of Rust
#60Earlier quoted context omitted.
It's a surprising choice that Rust made to have the unit of compilation and unit of distribution coincide. I say surprising, because one of the tacit design principles I've seen and really appreciated in Rust is the disaggregation of orthogonal features. For example, classical object-oriented programming uses classes both as an encapsulation boundary (where invariants are maintained and information is hidden) and a d…
The history here is very interesting, Rust went through a bunch of design iteration early, and then it just kinda sat around for a long time, and then made other choices that made modifying earlier choices harder. And then we did manage to have some significant change (for the good) in Rust 2018. Rust's users find the module system even more difficult than the borrow checker. I've tried to figure out why, and figure…
The module system in Rust is conceptually huge, and I feel it needs a 'Rust modules: the good parts' resource to guide people.
(1) There are five different ways to use `pub`. That's pretty overwhelming, and in practice I almost never see `pub(in foo)` used.
(2) It's possible to have nested modules in a single file, or across multiple files. I almost never see modules with braces, except `mod tests`.
(3) It's possible to have either foo.rs or foo/mod.rs. It's also possible to have both foo.rs and foo/bar.rs, which feels inconsistent.
(4) `use` order doesn't matter, which can make imports hard to reason about. Here's a silly example:
use foo::bar; use bar::foo;
(Huge fan of your writing, by the way!)