Why use Rust on the back end?
blog.adamchalmers.com
blog.adamchalmers.com
You have to be willing to believe that and consider it when hiring, of course, which some organizations may reasonably not be willing to.
It mostly depends on what you have in you brain, what you see when you look at code, and if you understand why you do what you do rather than repeating a trick and hoping it works, and I suppose that is a combination of theory and experience.
I think it's exceedingly difficult to make such a broad generalization. There's a number of factors here at play, but for example, I think the struggles of a Rubyist learning Rust are very different than a C developer learning Rust, and are very different than someone who's proficient with both who is learning Rust.
It's also hard because there's also just other random factors. There's a semi-common experience where people try Rust, think it's too hard, quit, and then come back 3 or 6 months later, try again, and are completely unstuck. Sometimes it takes coming back two or three times. Do you count all of that dead time? Something in there helped, but it's unclear what, or why this affects some people.
Another theme of stories I've heard is a sort of Golidlocks situation about how "right" you think the compiler is. Some folks have the attitude that the compiler is to be seen, not heard, and should stop nagging them about things. Those folks tend to really struggle with Rust, even if they have lots of relevant experience previously. Likewise, some folks trust the compiler so completely that they will lose a bunch of time when a compiler suggestion leads them down the wrong path. Luckily, that problem is easier to fix than the former one, and is rarer and rarer every day. But these sorts of attributes are completely separate than what we think of when we talk "competency" of devs.
> In your experience, what's the best path to learn Rust in 2023?
This sounds tautological, but bear with me: it's whatever path gets you to learn Rust. That sounds trite but what I mean is that different people have different needs (see above) and so need different things. There is no one best way. For some people, the book works really, really well. For others, they either hate the writing style, or the pace, or just something ineffable. I wouldn't say that they're wrong for that, just that they'd be served by different strategies.
What I will say is that "I know other languages, I can just kinda start coding and pick it up" tends to not work for almost anyone. You either need to be quick to ask questions from the community, or be willing to do some reading, or you may run into some struggles that will take you longer to overcome than if you were willing to get some help. Folks who take advantage of community resources, broadly speaking, tend to do better than folks that think they can write some code and learn solely through errors, as Rust's semantics are just unique enough that some background and explanation can be extremely helpful.
This was my experience, I came back a year or two later, and both I and the language had improved. I'm not sure who improved more, but whatever happened I'm really enjoying the language now.
There's a lot of good docs like rust-by-example and the rust book, but for my liking, those both seem to spend too much time on each topics rather than distilling the info into smaller denser topics. This is probably great for newer developers but more difficult for someone that wants to learn the 30 second version of something rather than the 5 minute version. It's possible that punching these books through a GPT prompt like "Extract the salient points from the following:" might help?
I think the issue happens when you have a new rust/go/javascript/etc. dev trying to setup a project for the first time.
I honestly have no clue how someone without low level experience (eg. never did systems level programming) even approaches Rust.
The ownership model makes sense to me but if I had to grok manual memory management and rust abstractions on top of it at the same time I think I would be unable to contribute even trivial stuff for a month.
Oh and coming from a dynamic language background at that ?
Not saying can't be done just saying time till contributing is probably weeks-months.
With go it's probably days.
In my personal experience you do this by writing your programs in such a way as not to require complex ownership. I had an easy time writing web services where the only cross-request shared state was a database handle. I had a hard time when I had to write a websocket document sync serverwhere I needed per-document global state shared between all the handlers, and I eventually gave up and moved to a model where a language with an easier concurrency story called rust code.
We generally consider our rust backend as two parts: application code and library code. We intend for our application code to be approachable by full stack developers and not require deep rust expertise to use. Our library code can be a bit more complicated, and there we see a bigger ramp up and frankly some self selection among our team and that's fine.
I started by reading the Rust Book. It explains most of the low-level concepts. It took me about a week of mostly just learning and experimenting, and another ~3 weeks until I had an MVP of my system. But from there it was just another 2 months until I had a full system written and in production, which it would probably have taken in another language anyway (as the project involved a lot of trial and error reversing a (simple but) only partially documented format).
Perhaps it helps that I came from JavaScript where a lot of the abstractions are similar.
There was an optional operating systems paper which had you writing some assembly to run on an in-house RISC system [1], but a small % of CS+SE students took that paper.
I think they’re trending towards using Python for most papers now. Not unreasonable for a paper on data mining or web development, but there’s definitely something being lost where students don’t /need/ to understand how the computer’s working in order to get a passing grade, so there’s no real incentive to dig deeper for the average student.
Far easier than the way anyone without low level experience (which meant almost everybody starting out) approached learning C and C+, back when Java, C#, Python, Perl etc were not yet a thing, and you got either got directly into C/C++ or started with PASCAL and BASIC if you were lucky. Oh, and no IDES, internet, stack overflow, or forums either...
On the other hand, if you need manual memory management (for performance reasons, or because you're doing something bare-metal), you'll be fighting Go's garbage collector, and Rust has conveniences for manual memory management that Go doesn't.
Above is a question, not a snark. I like learning languages and haven’t dabbled in Rust so am curious.
There's a different sense that I feel is being overlooked by those people in that the problems you run into with Rust are frequently actual flaws or bugs in your code, and the compiler shouldn't be thought of an adversary blocking your way to feature development but a teacher showing you the things you're overlooking. So once you put in the upfront cost of learning how to write Rust that compiles, you get code that's much more maintainable, correct, and easy to refactor.
So for someone that likes learning languages, I'd say choosing to learn Rust is a great choice and will teach you things you can take with you to other languages.
Whereas in Rust I was able to keep going. Sometimes, when I dug down I reached something truly enlightening like the implementation of core::mem::drop -- pub fn drop<T>(_x: T) { }
[ Yes I said implementation, that's not a typo, that's the actual implementation. ]
Sometimes, it's all fucking turtles, e.g. Aria's famous "Pre-pooping your pants" essay and her "Tower of Weakenings". There's bad news, but if you don't like that we also have more and different bad news.
And sometimes it was a voyage of discovery, but it was an interesting voyage, I learned much and I felt invigorated and encouraged. For example why C++ std::vector's reserve is not Rust's Vec::reserve but Vec::reserve_exact or why Rust's functions each have unique unnameable types, or how MaybeUninit actually works.
The very last thing I'm here to do is to advocate for Go over Rust, or vice versa. But there are some basic facts about the languages we should be able to recognize, without falling into a bottomless pit of language war. Rust is more complicated than Go, and it's that way for a reason: you can readily use Rust in problem domains that don't admit Go.
But alas, Go's quest to avoid being clever often means that when the simplest thing would be too clever that must be avoided. If you are implementing Go this is presumably a great convenience, but I'm not implementing Go, I was just trying to write software.
Rust and Go agree that 1 == 1 and 5.26 == 5.26 and "New York" == "New York", but then Go wimps out. Rust has no problem if we should like to use this equality operator on arrays of integers, or slices of booleans, or for that matter HashMaps of HashSets of Vecs of Strings, but that's all too Clever for Go, so in Go we must use extra functions like reflect.DeepEqual.
Rust and Go both agree there's fundamentally only one loop. But, they disagree on what that fundamental loop is. Rust's fundamental loop is named "loop". It just loops, forever, it's a loop. Go's idea of a fundamental loop is a variation on C's for loop it uh, well it has two statements, plus a boolean expression, the expression is tested before each iteration and the first statement happens once, but the other statement happens after each subsequent iteration. That... doesn't seem simpler. I'm not sure what their excuse was here, is an infinite loop too Clever ?
There are a few more like this. Unsafe Rust is definitely way more complicated, but one of the less obvious benefits of that keyword is that it tells beginners what they don't need to know about. Ah, this is marked unsafe, I'm a beginner, no need to explore that yet.
Probably you can argue that the need to teach 'lifetimes undoes all this benefit and that's still safe Rust. It's a position I don't have hard data to refute, just my personal experience, for whatever that's worth.
Maybe I'm missing some key context, but I've never reached for reflection in the scenario you've described.
Geniunely curious since the company was found 3+ years ago (2019).
https://oxide.computer/blog/introducing-the-oxide-computer-c...
We also have a ton of projects on our GitHub, including the web framework we developed for our API that I’m alluding to above. Of course, that’s not the core product, but you can see what we’ve got going on.
For some reason, people act like being a C# or Java dev means that you’re an idiot. If you’re skilled enough to be writing quality high-performance code in those languages, learning Rust is not a huge barrier…
But, I work with a lot of college students who are just beginning to learn software development, and the realization that that kind of generalization is possible is not obvious; and a lot of people who are only a few years into their career--but maybe think they are pretty damned good at it (I look back at myself when I had a mere 10 years of actual-real-world experience and think just how much I still had to learn to become who I am today... I am thankful I worked with some gods and always knew I had a long way to go)--not only have a hard time learning a new language (I remember when I was in high school trying to learn Pascal after I had spent years coding in Visual Basic and even getting paid to do so, and thinking I knew C... I did not ;P) but internalize how daunting it is and then go really far out of their way to avoid learning new languages (which, thankfully, I could not as high schools at the time were ping through a big upset in curriculums and so we learned a new language every year for a while and I got recruited to help my AP Computer Science teacher as he also was having to adjust way too quickly through Pascal, C/C++, and Java/JavaScript).
And it is actually quite remarkable how well people manage to do at this, using IDEs to avoid command lines and ORM technology and DSL compilers to avoid having to use SQL or other languages, they glom onto whatever ridiculous interop mechanism they can that prevents them from learning about low-level languages... and I think it really does hurt them, and I remember running into some software developers who did so well that they never managed to get to the right generalizations and they are now old and can still only program in one language (the same way I have a really really really hard time speaking in any language other than English); but like, most developers, no matter how hard they try, eventually do get enough exposure to enough at least slightly-different languages to get this skill (which is, when I get hired to teach courses, what I try to accelerate: Comparative Machine Language Morphology ;P).
But like, due to us all living in the Eternal September--and I do not just mean online: I was shocked recently when I learned how many CS students there are at most of the other Universities (it turns out the one I still live at is an extreme minority with only a few percent of the population being Computer Science and only half the students being engineering at all)--not only are we going to end up interacting directly with a number of people who actually do find learning new languages hard (and think it must fundamentally be hard for everyone forever), but I think we are going to run into a lot of managers on the front lines of trying to build businesses out of cogs (a practice I dislike on a number of grounds, but fully admit, if you can pull it off, is probably an extremely powerful and efficient way to do industrial/corporate engineering) who are also extremely resigned to the notion that the early-stage people they hire are oft incapable of learning new languages quickly enough to truly be a usable cog, as like... do they really even want to hire someone who has as much experience as you must (as the way you worded your comment implies you've been coding a lot longer than the mere 5 years you have been coding in Java/C# ;P).
Now I'm 41 and it's weird to be working with 21 year olds. Not bad but you just have these funny cultural differences.
IDEs, ORMs and other tools have their roles. They didn't get invented just because people are lazy and don't want to learn "command line" and SQL.
If you didn't have the occasion to experiences use cases where such tools are useful, that doesn't mean they aren't useful.
Otherwise you can argue that compilers are for people who are too lazy to write machine code directly.
Maybe it is true, for some people and for some languages.
However, learning the syntax of a new language means nothing if you don't already learn libraries, tools, frameworks, tools, patterns, idioms. And that still takes time.
Memory isn't unlimited and while you learn new concepts, try to make room for new concepts, you start to forget some of the old concepts, especially if you start using them less frequently or seldom use them.
To tell a quick anecdote: when Apple announced Swift, I was hearing about it for the first time in the audience at WWDC during the keynote. As I watched, it was quite clear to me that this was a language that was mixing parts of Scala, Haskell, and (awkwardly enough) Ruby with the background of Objective-C, and it just immediately clicked. I ended up giving a talk about the language a few days later at AltConf.
The reality is that, unless people go extremely far out of their way to push their language in a way that makes it awkward for the user--I had a student who designed an esolang based on gravity and "roadrunner physics" where the code was a map where things didn't start to fall until they had some kind of interaction--there is very little "new" under the sun: the vast majority of "advances" in programming languages were already pioneered many decades ago.
(The most ridiculously-obvious example of this is probably Go, which has almost nothing that wasn't already understood by the 1970s, including its mechanisms around channel-oriented concurrency. There is an amazing article that attempts to compare Go to a "Brand X" language that turns out to be Algol 68. But like, Rust's entire schtick--the reason it is called Rust!--is because they actively refused to do any new language research and instead based it all on well-worn concepts, and yet people still whine about it incessantly merely because they haven't put anywhere near enough time into learning about the history of programming.)
Now the challenge is to hire new developers that are not familiar with Rust; it would take a month or so for them to be productive (assuming robust internal code practice). But, well worthwhile in our opinion, as least for greenfield application/services.
(We are coming from Java / nodejs/TS)
Many of developers who are skilled in X can learn Y. But that doesn't mean you should hire X developers and ask the to do Y.
The process should be easy. Identify the tool which is most fitted for the project. Hire developers proficient in that tool.
It’s not to hard to learn. The Rust web stack is fairly simple and easy to get going with in a few days. Good developers use many languages and enjoy using many languages. If you drop the usual requires ten years experience you have just increased your hiring pool to a bunch of people who are excited to learn so will often put in the hard work to learn.
It’s a bit disrespectful to think a new grad can’t use a language other than JS/Python and they’ll be more productive in JS/Python. How little do you think of grads?
Rust has its place for things that need to be especially optimized. It's far too pedantic for the kind of things you can do in NodeJS or Flask. New grad would be annoyed, and so would I.
I've had GPT-4 explain to me weird niches in Django that I don't understand, because I'm coming from a Javascript background. It'll pick up what I'm trying to do, give me the code I'm trying to write, and tell me where I went wrong.
In the process I learn a lot, and waste a lot less time trawling Stack Overflow and parsing other people's code and closed threads.
It's a lot like having a more experienced developer over my shoulder.
Idk if you'd call it syntax or what, but what makes Rust pedantic is that you're always worrying about lifetimes, types, explicit errors (as opposed to exceptions), and other things you mostly don't think about in JS or Py. It's like C++ only nicer and safer. It's not that JS/Py is a lower skill, it's that devs don't want to waste time. Of course Rust or C++ makes plenty of sense for lower-level stuff or anything that needs to be especially optimized.
Rust is enforcing safety while C++ does not. C++ can be safe if you need it to be. Just use safe constructs.
I'd argue that some people might not find Rust nicer.
Knowing the language is necessary but not sufficient. There is an enormous amount of practice around language that is not implied by the language itself that you need to learn if you want to be effective.
I don't think that's really that big of a deal. Any above-average developer should be able to become useful in a new language in a pretty short period of time. They don't have to know the language on day 1, they only have to know how to develop software.
On the plus side, if you hire someone who isn't an expert Rust developer and they mess things up, it will break at compile time instead of at runtime.
Assuming you still have some Rust developers at your workplace, and assuming the new developer is not completely incompetent, they should be able to get up to speed before too long.
Safe Rust is not something that's going to be a problem for a good developer. If they've actually understood what they were doing in C# or Go, for example they'll be fine. It's another semi-colon language, they can be spun up on this language with the Book, or a day's Pluralsight or whatever makes sense.
Yes, Rust makes more sense if that C# programmer also dabbled in F# or maybe the Go programmer took a semester of an ML in college ten years ago, because hey, this semi-colon language is sometimes an ML in a trench coat, but that's not crucial to being productive.
If your software ends up with non-trivial amounts of Unsafe Rust then yes, you will need somebody who knows what the fuck they're doing. But that'd be true if you needed unsafe C# (yes, that's a thing) and again, there's a lot less experience with unsafe C# on the market just like for Rust. And if you've got a problem for which Unsafe Rust was appropriate you'd need all the help you could get in these other languages.
Than maybe it's easier to just use C or C++.
If your next task is to write a web api the sensible thing to do is to assign that task to a team of backend developers. Conversely, you generally don't ask web developers to do system programming.
- The API is likely to be simple (JSON in and out, or something similar). Those devs already know they domain well.
- The Rust compiler enforces only valid programs, so you won’t get runtime errors for things you would in dynamic languages.
- This leaves just getting the logic right, which the developers know how to do in general, and Rust is a c-like language so it’s familiar.
Fair that the author says that this is their opinion, however... I can't agree.
Maybe I'm too stupid, but for me SQLx is the real killer crate when it comes to databases.
Everything, from the migrate macro, to the way it validates at compile-time the types in the DB, feels (to me) very ergonomic.
Diesel, by contrast, I spent so long trying to set up and I never really understood the three different files that need to somehow be in sync and generated. I just never really grokked the split of these files and when to run the diesel-cli commands...
but SQLx is great, I often lament that there isn't anything comparable in Golang.
Also, testing is quite annoying too. If you're using sqlite, you can use in-memory mode and that's quite nice. But for other databases you basically have only two options: 1. setup and teardown an actual testing db 2. wrap your sqlx interfacing code in something vaguely resembling the repository pattern and create an in-memory implementation for testing. I'd call both of these options less than ideal.
The other option is avoid such a high stakes environment, but someones got to be in those fields.
Why not just BEGIN a transaction and then ROLLBACK it after every test case? That's what every other significant backend codebase (using SQL) that I've worked on does. Maybe that's what you meant by #1? Not sure why you'd want to avoid it then—it will help significantly in testing out any piece of code you have that's even slightly outside of the CRUD norms. What does Diesel do, reimplement a completely separate "testing" version for all of its SQL queries?
[1]: https://docs.diesel.rs/2.0.x/diesel/connection/trait.Connect...
* The sqlx::query! macro is a neat hack, but the fact that it calls out to a database in a proc macro is pretty insane. It significantly slows down compilation with a lot of queries, and doesn't work reliably with rust-analyzer.
* Inconsistent handling of nullability that would regularly break compilation
We now use Cornucopia (https://cornucopia-rs.netlify.app/) which I think is a much better approach. You write your queries in a separate SQL file, alongside annotations that let you specify nullability. A standard build.rs integration performs codegen from that, which means compilation itself doesn't require a DB and IDE features work well. It also lets you share data types between queries which reduces boilerplate significantly.
wait... proc macros are run at compile time, right? so db queries at compile time?!
but.. but.. why?
The real issue is that in performance benchmarks Diesel beats SQLx, at least last I checked. I'm hopeful the rewrite/upgrades to SQLx that are coming shorten this gap.
This is just ensuring it is valid at compile time.
On deploy you just run your migrations first. Obviously you have to do some planning.
It's a major productivity boost honestly, after building a semi large app with it.
And yes, it does actually run the queries. It populates dummy data and runs it in a transaction from what I can tell.
It's honestly very nice. The code, my migrations, my DB browser, all in one window in my IDE.
And the query is validated by running it, at compile time, by inserting mock inputs inside a transaction. It works really well.
Even if you disagree that the DB must be the source of authority and it can differ, the development boon of the process is worth the 5% chance there is some issue later, which can probably be easily resolved.
your infrastructure is not that .tf definition, it's whatever is currently deployed to ec2
in the same way, your schema is not that .sql file, it's whatever the database says it is :)
You can keep pushing this argument but it doesn't mean anything in any practical sense.
(You can also check in the results of the database queries, so you only need the db in the build stack when you touch db-related code).
Yes, but it can also run in 'offline' mode where it builds against saved metadata [0]
0: https://github.com/launchbadge/sqlx/blob/main/sqlx-cli/READM...
The idea is kinda neat but....
Compile time verification that you haven't made a typo in your SQL, and that if you have updated your db schema that your code also reflects these changes.
Turning runtime errors in to compile time errors is one of Rust's superpowers.
Regarding your second bullet point, can you elaborate more? I haven't seen this. You have to explicitly use Option<> for non null columns but that's what I expect.
I 100% agree with your point about Diesel's dev experience leaving a lot to be desired when it comes to docs and ease-of-learning though. But to me, that is a straightforward problem to solve when compared to the fundamental limitation of sqlx that I described above.
I think it will require some thought. I hope that, once I get around to using diesel in a second substantial project (already using it for my first), I will write up my thoughts on how to make DX better for diesel.
Basically, Rust fulfills the dream of a functional language with pragmatic semantics, syntax, and developer experience. That's why I write it.
I don't think that's an accurate characterization of "the Rust crowd," but even if we do take it at face value, it would make sense: Rust was intended for the layer of the stack where these things do matter. Even though Rust has broken out of that initial layer, as the post demonstrates, culturally these things are likely to hold a bit more value than they may otherwise.
Good point. If those things don't matter, then maybe you are better off using another language.
Yes there is a skill gradient, but everyone who doesn't climb that hill is a fool and a weaker team member for it in my opinion.
OCaml or StandardML, (or Haskell if you want to get funky ... I don't), F#, Scala, etc.
Hell, these days even Swift, or Kotlin, have these features. Which I'd call: modern static type systems.
And I understand even Java is getting some of them. Even TypeScript is a reasonable-ish solution with a pretty nifty type system, if you don't mind the (non-existent) threading model.
I like Rust, but its niche is: the above nice things and a clean syntax, but without the latency&pause costs of GC. And that's what I use it for, when I need that kind of thing, for systems programming. And for that, the killer feature is the borrow checker which makes using the above features relatively painless, despite having no GC.
(Now one other advantage of the borrow checker is its application to concurrency -- making ownership of locks, and mutable state generally, easier to reason about. That's perhaps a killer feature that the other languages I mentioned don't really have)
You might want to explore the space of statically typed functional programming languages a bit more. OCaml and F# are both very pragmatic functional programming language that will give you everything you want and even more.
And really, you can see the priorities in how the people driving the language talk about it. In Rust there's a focus on ergonomics. How can we make this easier to use? How can we make the tooling nicer? In OCaml and other languages the focus is almost always on semantics. We have unboxed types like Rust. We have multicore with green threads. We have effects. This is missing the point. I don't care about the features of the language if the language itself is annoying to use. It's like wondering why Slack or Discord won versus IRC. Ergonomics is the answer.
I mean, OCaml's autoformatter just autoformats arbitrary Ocaml files. How do you blow that out of the water?
rustc’s error messages are _unbelievably_ nice. It’s shocking how much better they are, even compared to other modern languages. Error messages aren’t an arcane invocation that needs to be deciphered—they almost always explain exactly what went wrong, with suggestions for how to fix the issue.
I wish other languages had the same focus on DX that Rust does…
You might want to take a look at F#.
The problem is, where the hell is the enthusiasm for those languages in a similar direction as rust?
The only reason I don't use those languages is because people are overwhelmingly more enthusiastic about rust, which has the majority of features I want. This in turn makes rust have a better developer experience as more people use and contribute to that experience
I ported a program from C#, to F#, and then to Rust. The F# -> Rust conversion was a lot of "add curly braces and parentheses" and "replace |> with ." It's almost kind of ridiculous how similar the code can be. I've been going back and forth between F# and Rust on hobby work and it's very, very easy to do.
You get the equivalent of many crates of cross-platform stuff straight out of .NET Core: e.g serialize to/from JSON, network requests, tasking/async, etc. Either VS or Rider is great, the debugger also works out of the box. I also skip Python/Powershell/Bash and write any extra scripts I need in F# and run then with ``dotnet fsi``. This "Keep all the things in the same language" is very attractive to me. Using F# over Python for scripting is very enticing to me -- good implicit typing, enums, ``match``, etc. I'm not sure why this hasn't been pushed before.
The docs are great and most things "just work", but I've been trying to hold back my enthusiasm because I just haven't been able to find folks using it, and http://forums.fsharp.org seems empty. It is fun to write though :)
This choice is almost always more about the team than the technology, regardless of the specific language or framework or widget.
And in the current economy of random mass layoffs, any morale boosters you can find will matter more.
Especially the all-important advice: use Haskell when everyone on your team uses and wants to learn Haskell! Can't stress that enough. From experience, even when a language has all of the technical features to merit consideration for a project, what your developers are already familiar with will trump them all.
I wish it were a purely technical decision what language to use for a project but it's not. "Use the right tool for the job," is not the right advice for choosing a language. It's a social/network-effects type of decision.
Everything in Haskell is an academic exercise with very little to show for it in the end. The performance is not that great, and even with "fearless concurrency", most complicated performance tuning situations are entirely consumed by understanding the intricacies of GHC Haskell and how to best tune your program by letting GHC abstractions leak into your code in the appropriate places to get it to run fast. People constantly keep reinventing streaming libraries because there are always problems or compromises, etc etc.
I really used to be on the haskell bandwagon for many years, but these days, when I reach for it, I end up really wondering why. Even the dev tooling is still bad, slow and buggy.
Being able to write a lot of functional Rust and drop down to imperative/mutation when necessary also eases the curve compared to Haskell.
> 95% of the unwraps in our codebase are in unit tests.
There's a crate for that: https://crates.io/crates/testresult
Rust's ecosystem does an admirable job in making it less painful to use, but I am still waiting for the day when just chuck any type into Gc<T>. Rc<T> or Arc<T> is not an alternative here. A garbage collector seriously makes business logic way easier to write. And none of rust's other advantages can offset this for Web development.
I know there have been attempts at general purpose garbage collectors for rust but as far as I've seen none of them seem to work seamlessly. Some justifications I've read about it go along the lines of LLVM not having native support for stackmaps?
And given how you have unmanaged native pointers lying around everywhere, I don't know if you could even have a general purpose GC without putting heavy restrictions on code that uses it effectively creating a split dialect.
I'm expecting my own comment to be downvoted as well, so I'll give a huge disclaimer that I lack experience with Rust, but I always find myself playing type tetris and having to think hard about memory management whereas Clojure, JavaScript, and Python all have interactive solutions that let one quickly hack together some web server and endpoints.
I don't say this from a perspective of distaste. I really like rust's ecosystem and tooling, but would really love to use `RustScript` one day which is basically Rust with a hint of Go. Green threads and all references can be treated as if they are effectively pointing into the heap.
- use `&mut` references to allow the borrow checker to statically enforce only one reference to the IP exists at a time (the major unique feature of Rust is the borrow checker which basically only allows one mutable reference at a time
- use an `UncloneableIp` new type that doesn't implement `Clone` to prevent the IP from being copied
I understand the two statements above in the article, just not how they can be made to work in this case. Apologies again if this is an obvious question, as I was saying I am definitely just starting out in rust.
Hopefully that gets the gist of how you might approach it. I'm not sure I'd use the HashSet myself, to be completely honest, because it makes it needlessly complicated to get an element out of it. I'd probably just use a Vec.
I don’t find a strong case for using Rust just to guarantee each thread gets its own IP (a mutex protected getter seems like it would do just fine for just that) but I guess it would guarantee that as long as you use this “uncopiable” object you could not, even if you wanted to, have two identical IPs in your program if I understand things correctly, which if your mutex getter had a bug would not protect you against.
I think that mutex are actually a really good example of what he's talking about in the article. You can only access the data from a Rust mutex through a `MutexGuard` returned from the lock method. `MutexGuard` is uncloneable and therefore, when it is dropped at the end of its scope, the mutex knows that it is free and can automatically unlock it. Additionally, it is impossible to access the data without having the `MutexGuard`, so you can statically determine at compile time that all data access is behind a lock.
Oh man have I felt this pain, trying to do anything mildly complex with Diesel's types is so ridiculously difficult. I once (foolishly) tried to write a generic repository implementation for database entities which could either have sqlite or postgres as a backend. I thought this would be very convenient for testing, being able to just keep all of the code the same safe for using a sqlite backed repository instead of a Postgres one.
I gave up after about ~10 hours of battling incomprehensible error messages.
And my system is safer in the end because I take that time I would've spent fighting the type system / tooling and instead spend it writing integration tests. I get to do full TDD often. And the bugs I catch are never due to mishandled types.
I'm a type-safety kind of guy, but this argument (that time spent "fighting" the type system) is better spent writing tests when it comes to DB queries, has me very very curious. Would love others' opinions/experience on this!
> I once (foolishly) tried to write a generic repository implementation for database entities which could either have sqlite or postgres as a backend. I thought this would be very convenient for testing, being able to just keep all of the code the same safe for using a sqlite backed repository instead of a Postgres one.
It's generally not advice to test against different databases than you run in production. This is one of the reasons why these kind of things are not simple in diesel. Prefer running the tests against the "real" database system and use `Connection::begin_test_transaction()` to prevent polluting the database with test data.
More generally speaking: Writing generic code involving diesel is likely an advanced topic, so don't expect it to work quickly. I usually advice people to not write this generic code, at least not if they just want to use diesel in their applications.
[1] https://github.com/Keats/validator/issues/201
[2] https://json-schema.org/implementations.html#validator-rust
This is akin to a construction company saying: "We already have some carpenters, let them do the bricklaying and use their hammers while at that."
What happened to the right tool for the job?
I see Rust as a specialized language, fit for specific problems. If you need performance, need low level access to the hardware and also need the kind of safety guarantees Rust provides, then is the right tool for the job.
Using Rust for backends can be as good an endeavor as using Go for writing device drivers.
So my only choice if I want to use Rust is to leave the company, but it's really hard to find other companies that primarily use Rust. The majority of the ones that do are crypto/blockchain related or doing something extremely low-level or out of my wheelhouse since they assume you're also comfortable with writing C++. I'm primarily a web developer and I hardly see any web startups choosing Rust.
I recently revisited a Go project that does a bunch of async tasks right after doing a somewhat involved Rust project, and all I could see were foot guns everywhere, even though most of it was considered the idiomatic approach.
The problem is when you start to have to dealing with edge cases or want to express complex invariants statically. Fasterthanlime's articles, though IMO a bit excessively long-winded, are some of the best, most damning critique of Go's refusal to support correctness-by-design in a disappointing number of areas.
What's the most mature web framework and how does that compare to working with basic Servlets sans Spring?
Never wrote a Java web server sorry cannot compare.
Granted, for their task this was over complication, but if they were doing ads (or something similar) it always needs ways to structure your data, and then you end up needing something hierarchical, typed, extensible with backward and forward compatibility (e.g. in protobuf for example, never reuse already used index field, etc.)