16 ms·
I love building a startup in Rust but wouldn't pick it again
- Nevin1901 4y agoFor apps where performance is key, I found you can get by using go for an MVP. Apart from the spikes in cou usage because of the garbage collector, go is fast and allows you to iterate quickly.
- PaulHoule 4y agoI can't get it why people would prefer to add "?" to everything instead of just having exceptions which automate that behavior. In the bad old days of C there were two kinds of programs: programs without correct error handling, and programs where half the loc are unhappy paths that do what exceptions do... with a huge amount of work. Today people are repeating the same mistakes of the past, putting a "?" on everything is a lot better than what you had to do in C, but why do that when you can just use a language with exceptions? It is like somebody showed cavemen fire (exceptions) and they decided it wasn't worth anything and went to go screw around with other things.
- nemothekid 4y agoI prefer having extra work done writing code (adding "?") than having to do extra work reading code. Exceptions are functionally invisible control flow; it isn't clear to the reader that a function may blow up if the exceptions are unhandled.
- Jensson 4y agoIn Java functions declares Exceptions in its type signature, so it does all of that automatically. Then you get a compile error if you don't handle it in the function, or you need to declare the function throws it, so it is type safe. Note that people now consider that as a mistake, people prefer having Exceptions be hidden instead of explicit and requiring handling like that.
- jb1991 4y ago> Note that people now consider that as a mistake, people prefer having Exceptions be hidden instead of explicit and requiring handling like that. Well, Swift is a much newer language than Java, and exceptions in Swift cannot be hidden either. And some people do rather like this.
- rom-antics 4y agoThe mistake was not "explicit errors". It was having a mix of error types, some explicit and some implicit, with no convenient way to combine them, plus the interface complications. Note that most newer languages are choosing explicit errors. This includes at least Go, Rust, Swift, Zig, and Odin.
- hinkley 4y agoThe second mistake was only flirting with Bertrand Meyer’s work until the Gang of Four showed up and wrecked Java forever. Meyer + functional core nets you a great deal of code with no exception declarations and an easy path for unit tests. If it hurts to do stuff it might not be the language that sucks, it might be you. Pain is information. Adapt.
- theptip 4y agoDon’t know Meyer’s work - any suggestions for good starting points?
- hinkley 4y agoThere’s the Design By Contract work of course, but I’m still trying to cite what I thought was his best advice which is to separate decisions from execution, which is compatible with but I find to be subtler than the functional core pattern. Often we mix glue code and IO code with our business logic, and that makes for tough testing situations. Especially in languages that allow parallel tests. If you fetch data in one function and act upon it in another, you have an easy imperative code structure that provides most of the benefits of Dependency Injection. Your stack traces are also half as deep, and aren’t crowded with objects calling themselves four times in a row before delegating. if (this.shouldDoTheThing()) { this.doTheThing(); } Importantly with this, structure, growth in complexity of the yes/no decision doesn’t increase the complexity of the action code tests, and growth in glue code (auth headers, talking to multiple backends, etc) doesn’t increase the complexity of the logic tests. A big part of scaling an application is finding ways to make complexity additive or logarithmic, rather than multiplicative. But people miss this because they start off with four tests checking it the wrong way, and it takes four tests to do it the right way. But then later it’s 6 vs 8, and then 8 vs 16, and then it’s straight to the moon after that.
- jb1991 4y agoIn Swift, at least, the possibility that a function can throw must be marked as part of its signature, and the exception cannot be ignored if it is thrown so the call requires explicit syntax as well, so there is no way to miss that something could "blow up" when reading the code.
- eunoia 4y agoIt's a little old at this point, but I find the Swift Error Handling Rationale design doc to be absolutely fascinating. It cites other language’s error handling paradigms (including Rust) if you're curious: https://apple-swift.readthedocs.io/en/latest/ErrorHandlingRationale.html https://apple-swift.readthedocs.io/en/latest/ErrorHandlingRa...
- jb1991 4y agoFascinating, looking forward to reading this later today! Have used a handful of languages over the years, and I don’t have any academic perspective in different error handling techniques, but there’s no doubt that the way swift does it feels particularly natural, safe, but still gets out of your way. I love all the options for handling errors in a meaningful way.
- taeric 4y agoI get where you are coming from, but imagine if every other "to the human" process description we had was done this way. I actually think this would be a fun one. How to make scrambled eggs, but where all failure cases are covered. Would be the "Hal fixes a lightbulb" in prose.
- sowbug 4y agoThat gets to the original promise of computers, doesn't it? That they'd perform repetitive tasks quickly and reliably. Meanwhile, every time I make scrambled eggs, there is a small but very real chance that my house burns down. And we accept this because to err is human.
- taeric 4y agoSorta? But a lot can be packed away in "other directions." Most recipes, for example, assume that setup/teardown is intrinsic to the kitchen. As such, to know the procedures to do those things, you would look somewhere else. That is, you aren't accepting a risk that things will go wrong. You have moved what to do about many exceptions to somewhere else.
- wvenable 4y agoAssume all functions can throw and there is no extra work reading. A function that has no possibility of error is so uninteresting in the context of error handling. Furthermore, handling errors has little to do with where the error is actually caused. In general, you can only do two things with errors: log and kill the operation or retry the operation. Neither of these has anything to do with the leaf function 20 items down in the stack that actually made the network call that failed.
- sanderjd 4y agoWhat you're describing here are unchecked exceptions, which Rust has in the form of panic. There are other kinds of errors that can be handled closer to the point where they occur.
- nemothekid 4y agoIf I am in the business of writing robust code; then "assuming all functions can throw" means at the very least forcing every function call to be surrounded by a try/catch block? It almost always make sense to handle an error locally if you can; for example if I want to retry the operation (let's say I'm writing a distributed database client), it may make sense for me to retry another node rather than unwinding to the application level that has now lost all context. >A function that has no possibility of error is so uninteresting that focusing on that is the wrong thing. I spend a lot of time debugging errors in code that has 0% chance of failing. It tends to involve a lot of matrix math. This isn't something you can say is universally true especially given all the hype around AI now.
- quietbritishjim 4y ago> It almost always make sense to handle an error locally if you can This is highly presumptuous. I have written many programs that did not need to handle errors locally, and so exception handlers were only at the very top level (or, actually, just below the top-level usually - but the point is that there were generally few and I had flexibility to decide where to put them). Perhaps you and I write very different applications. But the fact remains that the "almost always" in your statement doesn't hold. Alternatively line of reasoning: if this was always true then there would be little point to Rust's ? as it would be so rarely used.
- PaulHoule 4y agoExceptions always work the same way. You learn how to read code with exceptions pretty quickly.
- frodowtf 4y agoHow does an explicit raise operator like '?' work any different than that? You can learn how to read it pretty quickly.
- einpoklum 4y agoYou may prefer that, but everyone else who has to read your code - doesn't. Yours is an approach which is likely to ensure your code is discarded and has to be rewritten relatively quickly.
- adamnemecek 4y agoThey are not the same. Errors force you to explicitly handle unexpected conditions. Exceptions don't. And "?" is for making error handling not take up half of loc. Read up on how exceptions work in C++ implementation-wise. It's not pretty.
- PaulHoule 4y agoThat's C++. It puts the C in Cthulhu.
- saurik 4y agoThat's the problem, though, right? 99.999% of the time you absolutely should not be "handling" an error: you should merely propagate it so it gets closer to code that has actual intent. Languages that force you to try to "handle" errors--which includes Java, due to their botched concept of checked exceptions--both encourage the wrong behavior in the developer and cause the code to be littered with boilerplate to implement the propagation manually. Meanwhile, they manage to encode the concept of "can fail" into not merely the type signature of a function but into the syntax used to access it, when--like other monadic behaviors, including "requires scoped allocation"--this is the kind of thing you tend to need to refactor into a codebase at a later time: instead, the code should always be typed as if everything can fail and everything can allocate (not just memory, but any resource); languages that get this right--such as C++ and Python--thereby deserve their stickiness.
- veqq 4y ago> you absolutely should not be "handling" an error: you should merely propagate it so it gets closer to code that has actual intent Why?! There are 2 types of errors: - an error in your program logic, which you need to fix - an error from something out of your control (network down, disc errors, faulty input... Which you certainly must handle What's the alternative? Let errors trigger undefined behavior and corrupt your DB? Not pretty.
- jiggawatts 4y agoExceptions are not "undefined" behaviour, and they don't "corrupt the database". On the contrary, they're very often used to abort database transactions cleanly, even in complex chains of deeply nested function calls. What people mean by "not handling errors" is that the Visual Basic style of "On Error Resume Next" is a terrible, terrible thing to do. The equivalent in modern languages is a try-catch block in the middle of a stack of function calls 200 deep. That function likely has no idea what the context before it is. Is it being called from a CLI? A kernel module? A web server? Who knows! Just yesterday I had to deal with legacy code that made this mistake, and now it's going to cause a multi-day problem for several people. It's a ASP.NET HTTP authentication module that simply swallows exceptions during authentication (e.g.: "Can't decrypt cookie"), doing essentially nothing. When deployed "wrong" (e.g.: encryption key is invalid) it just gets stuck in a redirect loop. The authentication redirects back with a cookie, it is silently ignored, then it redirects to the authentication page which already has a cookie so it redirects back, and so on. There is nothing in the logs. No exceptions bubble up to the APM or the log analytics systems. The result is HTTP 200 OK as far as the eye can see, but the entire app is broken and we don't even know where or why exactly. That's not even mentioning the security risks of silently discarding authentication-related errors! This is what people mean by don't "handle" errors. Middleware or random libraries should never catch exceptions. It's fine if they wrap a large variety of exception types in a better type, but even then it is important to preserve the inner exception for troubleshooting. I've had to tell every developer this that I've worked with recently as a cloud engineer. Stop trying to be "nice" by catching exceptions. Exceptions are not nice by definition and ignoring that reality won't help anyone.
- taeric 4y ago> and programs where half the loc are unhappy paths that do what exceptions do... with a huge amount of work. This made me laugh harder than makes sense. I'm sure I've been guilty of doing said code, as well.
- jakelazaroff 4y agoExceptions come with their own weirdness. Usually, if you want to handle an exception, you need to wrap the code that could generate it in a block, which means any variables declared there won't be available in the parent scope. I'd much rather have the ability to just write normal code and deal with the error on the spot, along with some syntactic sugar (such as "?") to return that error to the caller.
- deleted 4y ago[deleted]
- larusso 4y agoHow would an exception automate the behavior of „?“? What ? does in rust is to unwrap the result check if it is err and return from the function with an error result. On top of that it will auto-convert the error type (if the type has the from/into traits implemented) So it would do: try { //the code that may fail } catch (error) { //do we just throw the same error? //or convert the exception to a custom other exception } If I see an API that throws me an low level exception without context I go mad. Like an file not found exception etc when executing an API that does multiple file IO operations.
- pclmulqdq 4y agoThere's some subtlety here: 1. Exceptions have very high performance costs (equivalent to a longjmp which is very slow), so if you expect to have exceptional cases, it's probably a lot more efficient to not use exceptions. 2. Exceptions break the linear flow of the code when you read it, so now you have to read a lot more code to figure out what the exception paths are and where and how they are handled.
- codethief 4y ago> Exceptions have very high performance costs (equivalent to a longjmp which is very slow) Could you elaborate on why they are so slow, compared to passing around/returning error objects explicitly?
- pclmulqdq 4y agoThey are slow because you need to restore context from an unknown/unpredictable place in the code, you have a table lookup (from a very cold table) to get the next program counter value, and you have to save and restore register values, while the callstack and the calling convention handle all of that complexity for you if you don't break the natural flow of the program.
- codethief 4y agoBut couldn't one implement exceptions internally by returning error codes? Yes, this would change the ABI but as long as we're not talking about the interface of a library, i.e. are not leaving the realms of our source code, this should be ok, shouldn't it? In a sense, try/catch would then just be syntactic sugar that frees you from manually checking for errors after every single function call. Instead, you just handle them in bulk in a catch block, potentially a couple stack frames further upstairs. EDIT: I just realized my suggestion wouldn't exactly be equivalent to exceptions, in the sense that it wouldn't give stack traces but error return traces, like in Zig: https://ziglang.org/documentation/master/#Error-Return-Traces https://ziglang.org/documentation/master/#Error-Return-Trace...
- chomp 4y agoIt's mostly philosophical, are you fine with blowing up with an exception, or would you rather have your functions return known values for the unhappy path? I personally like exceptions in exceptional cases, but much rather having functions with explicit contracts (e.g. "this will return either True or False in all input cases", not "this will return either True, or Exception in all cases when $foo doesn't exist in the database, and woe unto the programmer that forgets to catch this.")
- girvo 4y agoNim handles that with the {.raises: [].} pragma and the effect system, which is quite a neat approach. It’s like opt-in checked exceptions, but with much nicer ergonomics than Java used to have
- duped 4y agofn foo () -> Result<(), E1> { .. } fn bar () -> Result<(), E2> { foo()?; } This requires `bar` to have a function signature that notes it may error, `E2` must implement `From<E1>`, and the caller of `bar` must use the result or explicitly silence the warning. Meaning if a program creates a Result the error must be handled - you can't silently let errors bubble up through the call stack. `Result` implements some common combinators like `.ok()` to convert to `Option`, `map`, `map_err`, `or_else`, etc to reflect the common cases of error handling. And finally, since Result doesn't require non-local control flow like exceptions you know that `drop` will run as the functions return back up the callstack. And if you want to use Result like exceptions... you can. But you can't hide it from callers, and callers are still free to handle them elegantly.
- Larrikin 4y agoDespite what CS and SE classes try to drill into you, null results or failure cases are nearly always better handled right when they happen instead of passing them up with layers of exception handling. Log it, pass null up, and just immediately handle it. Fail early and none of the rest of the function matters. Even types of exceptions are rarely useful results outside of reading the logs or sometimes in libraries outside of your control.
- 8note 4y agoThe most important considerations for errors is whether they can be retried, and who needs to change something to fix it. The types can be useful for communicating this
- za3faran 4y agoHow do you handle a DB connection time out in your stack? You can log it and retry, eventually the entire call must be terminated though, and the quickest way is through exception propagation.
- jeddy3 4y agoIMHO both exceptions and error handling in Rust (and others) have their upsides and downsides. Personally, I much prefer Rusts solution, being both more up front and at the same time more terse. The metaphor is kinda stupid though, the "cavemen" in our scenario knows very well that exceptions exist.
- jbellis 4y agoError handling in Rust is actually a lot worse than you think. In fact it may be the single worst aspect of the language. Fundamentally it is difficult to impossible to fix bugs without knowing what code caused it. Java-style exceptions give you a backtrace for free, which is a huge head start. With Rust you have to do a lot of manual plumbing with something like error_stack to get similar functionality, out-of-the-box Errs do NOT capture this. Far more productive to work in an environment that does the right thing "for free" vs having to do it manually.
- dalyons 4y agoUgh that’s one of the worst parts of go too. Stackless errors are so useless and hard to debug.
- hobofan 4y ago> Java-style exceptions give you a backtrace for free, which is a huge head start. With Rust you have to do a lot of manual plumbing with something like error_stack to get similar functionality With crates like anyhow and eyre you also get backtraces "for free" nowadays, without needing to do manual plumbing (all you need to do is toggle on a feature flag).
- flohofwoe 4y agoThe problem with exceptions isn't the syntax, but the hidden control flow (they are essentially a goto in disguise). Error union return values make a lot more sense, the rest is just syntax sugar details (and that's where opinions differ I guess).
- gpderetta 4y agoExceptions are not a form of gotos, they are both less powerful as they are structured and more powerful (as they are nonlocal). They desugar to continuations, but so does rust option type handling and ?. In fact they are pretty much equivalent. I'm not terribly familiar with either language, but I don't see any particular difference between swift and rust error handling for example, swift will also mark fallible function calls with try, similarly to ? in rust. For what is worth the author of the swift standard library believes that try is a mistake: as most functions can fail in practice it just becomes noise. It might be more useful to mark can't fail regions.
- vore 4y agoI think the nonlocal part is the scary part: it becomes very scary to figure out which parts of the code can fail and how, especially when failures can come from an arbitrarily deep call stack. Maybe checked exceptions could be more useful to explicitly annotate allowed failures, but at the same time we all know how that's going in Java world.
- jstimpfle 4y agoIf you consider the case where you call a function that throws an exception without you expecting it -- then the control flow will skip your code, and this is indeed not very structured, like a goto, and in fact less local than a goto.
- flohofwoe 4y agoI was actually wondering (in Zig, which has a per-statement "try" which is essentially the same as the ? in Rust) whether it also makes sense for whole blocks, which would look a lot like traditional try-catch block in languages with exceptions, e.g. instead of: try may_fail_1(); try may_fail_2(); try may_fail_3(); ...this could be grouped into: try { may_fail_1(); may_fail_2(); may_fail_3(); } ...but would behave exactly the same as the indiviual trys, if any function in the block returns with an error, that same error is passed up to the caller. But I guess that forcing individual trys makes you think harder about handling individual errors than just pushing the responsibility for error handling up the callstack.
- MaulingMonkey 4y agoIn theory, I like exceptions. In practice, I hate them. Few languages statically check exception handling - e.g. Java, and even then only partially - leading to stability-ruining edge cases leaking into production in the most unexpected of places caught only by QA if you're lucky. Exception handling codegen can also be rather atrocious, leading to unavoidable performance degredation when third party middleware throws unavoidable exceptions, even when you do fix the stability bugs. They're also a nasty and reoccuring source of undefined behavior when they unwind past a C ABI boundary, an issue I've encountered in multiple codebases with multiple exception-throwing languages. In my personal experience, programmers are also rather terrible at writing exception-safe code. Result and ? force you to think about - or at least acknowledge - the edge cases. For a throwaway script or small scale easily tested program, that might be a drawback. For MLOC+ codebases where link times alone are sufficient to start impeding testing iteration times, it can be a big help for correctness and stability, while still being relatively lightweight compared to other manual error handling. Finally - Rust has exceptions. They're called panics. They can be configured to abort instead of unwind. This helps set the tone - they're really meant for bugs, and exceptionally exceptional circumstances. They cause all the problems of exceptions, too - unconsidered edge cases, undefined behavior unwinding past C ABIs, the works. Fortunately, it's reasonable in Rust to aim to eliminate all panics but bugs.
- PaulHoule 4y agoSee https://gen5.info/q/2008/07/31/stop-catching-exceptions/ https://gen5.info/q/2008/07/31/stop-catching-exceptions/ and https://gen5.info/q/2008/08/27/what-do-you-do-when-youve-caught-an-exception/ https://gen5.info/q/2008/08/27/what-do-you-do-when-youve-cau... It's very important to minimize the burden of handling errors in code with simple control flow. Frequently I see people try very hard to handle errors with monads in languages like Scala at the micro level and they are so burned out by this that they don't put any effort into handling errors properly at the macro level. If you make the micro level as automatic as you can it is possible devs will address the macro level, and what is necessary at the micro level is not dealing with a crisis that prevents the compiler from building your code, but rather cleaning up the environment consistently in both normal in error conditions and giving the macro level sufficient context for the error that it can do the right thing.
- User23 4y agoExceptions make it considerably harder to reason about state by reading the program text. As the notion that programmers should have some actual understanding of what they write slowly becomes less unfashionable, language features that make understanding code needlessly harder are losing some of their appeal even though they speed up writing the code.
- PaulHoule 4y agoWhat really makes code hard to read is having multiple paths to disentangle. There is one little error deep in the call stack but you have to vandalize the 10 functions above it in the call stack to carefully separate the error and non-error paths -- what's the probability that you will end up cleaning up properly in both paths when it isn't done for you with finally? What's the probability that somebody looking at this code is really going to find the subtle error in the error path or an error in the happy path caused and hidden by the complexity of the unhappy path? I think the first C program I saw was a type-in terminal emulator from Byte magazine around 1985 and I was struck by the akwardness of the error handling in the C stdlib, spent a lot of time looking at the code when I realized the author had "spaced it" at one point such that the error handling was wrong and thought "this sucks" but learned how to write C programs with 3x the LOC because of all the alternate paths I had to put in to handle errors. When I saw exceptions for the first time I felt strongly liberated because I got for free what I was working for so hard in C so I got to spend more time thinking about algorithms, the needs of the customer, things like that.
- Conscat 4y agoExceptions make it difficult to find failure-points in the code. The ? annotates that at its call site, which improves discoverability by a lot and reduces readability by only a little.
- lenkite 4y ago> Exceptions make it difficult to find failure-points in the code My experience doing Java, Go and Rust has been completely the opposite. Exception stack traces in Java are amazingly wonderful things - they exactly pin-point the failure points in the code. The amount of hunting I need to do to find out where something failed in the call stack in Go/Rust is tedious. You need a module/crate for error tracing or you up waddling against a strong current of despair.
- FridgeSeal 4y ago> Java are amazingly wonderful things - they exactly pin-point the failure points in the code. Yes. Once the exception has happened. At runtime. Which is not when I want to be trying to fix things. I’d much rather handle as much as possible statically, knowing that what I push into has every non-panic code path cleanly handled. I’ve never had the equivalent experience with exceptions, it’s always “well I’ve wrapped everything I possibly can in as much try-catch and handling as I possibly can, and oh look, some random piece of code has still thrown some random exception we’ve never seen before”.
- za3faran 4y agoYou still need a top level exception handler in your main loop.
- orthecreedence 4y ago> I can't get it why people would prefer to add "?" to everything instead of just having exceptions which automate that behavior. Exceptions? Which exceptions? How do you know which exceptions you're supposed to be handling and where they come from or when they happen? I prefer the control flow of the program and the exact types of errors I'm handling to be explicit.
- oconnor663 4y agoI mean, ask the C++ community. They've had exceptions forever, but a large chunk of them forbid exceptions in their codebases. I think there's a pretty good rule of thumb in modern systems-ish language design: If Go and Rust and Zig all do a certain thing, that thing is probably a great idea. These languages have very different priorities, but often they overlap.
- ngrilly 4y agoZig, unlike Go and Rust, provides an error return trace showing how the error bubbled up. This is a really interesting idea. https://ziglang.org/documentation/master/#Error-Return-Traces https://ziglang.org/documentation/master/#Error-Return-Trace...
- tbillington 4y agogo and rust both have this, though opt in at each location you're adding context.
- marcosdumay 4y ago> It is like somebody showed cavemen fire (exceptions) and they decided it wasn't worth anything Oh, it absolutely can not be that the Rust way is more powerful and you didn't understand it yet. No way. It's all those other people that don't understand the old concept that almost all of them know.
- jeremychone 4y agoAfter a couple of years of coding Rust, I found the error system, including the ?, well thought out. It is explicit and clear that the error is or maps to the function return error. The only thing is that Rust rightfully uses the ? to return early system on option as well, which removed the ability to have None coalescing with "?". This was the right choice from a language point of view, but I wish there would be a None coalescing syntax in Rust.
- mrichman 4y agoSo in his opinion, choosing Rust is a premature optimization?
- aisrael 4y agoAuthor here - yeah, that's how I feel about it, at least for startups specifically.
- mrichman 4y agoWhat if your startup is in the embedded systems space, for example? I don't think you'd be doing your MVP in Python.
- distcs 4y agoWhy impose the "embedded systems" space requirement on the OP? The OP does not work in embedded systems space. So it is not relevant to this article. The OP is telling us what they would do, not what you should do and definitely not what embedded systems startups should do.
- steveklabnik 4y ago(Not your parent but how I read it.) It's not imposing a space requirement. It's a reminder that these generalizations have limitations. The OP isn't in the embedded space, but they do say "a startup" not "a web startup." There are embedded startups.
- aisrael 4y agoThat's fair, I was definitely being a bit too general. There's another comment in this thread that summarizes it better which is asking "what would I use if Rust didn't exist?" and I think that's a more clear line. All of my embedded work was in C/asm so Rust is actually a great choice there.
- jeromenerf 4y ago... then however, how do you feel about tech debt with Rust? My feeling was that go, rust and such left a lighter burden on the future than say ruby. Do you think you will need a major rewrite soon?
- draw_down 4y agoThe doc about pinning seems really good. But I don’t understand what about it is necessary for something like middleware. Glad Rust is working for others, and I find it interesting to read about. but I don’t know if I could or would ever use it myself.
- newaccount2021 4y ago[dead]
- TuringTest 4y agoRust is a systems language, not a business language. If you're building an operating system or a software platform, to for it; the robustness will pay for itself in time to fix hard-to-find errors. But if you're iterating fast to find out what the program should be about to begin with, use a prototype-friendly language instead. With garbage collection.
- rattray 4y agoThis is something I hear a lot from other founders. Spinup time of new engineers is like 6mo+, some devs who can churn out normal CRUD product work just fine in Rails or React ~never become productive with Rust, and hiring skilled Rust devs is just crazy hard (though maybe now that Blockchain/Solidity things have cooled there may be more supply).
- rozgo 4y ago6mo+ is spot on. This is true for most dev work that deviates from the CRUD path. Like gaming, simulation, robotics. We might as well use the time to train them in Rust too.
- unshavedyak 4y ago> and hiring skilled Rust devs is just crazy hard (though maybe now that Blockchain/Solidity things have cooled there may be more supply). Sidenote, we hire Rust at a small shop (~30 devs?). Ironically i've found it _easier_ to hire for Rust. You're totally not wrong, BUT, the quality of the candidates that apply is quite high in our experience. I suspect it's because we get a lot of passionate people. We don't have to weed out as many candidates. With that said we don't aim for super senior devs. We're happy to hire a junior, etc. I care much more about the quality of the person than raw experience. With that said traditional hiring avenues have not been fruitful for us. Word of mouth, Rust community job posting, etc have been most fruitful by far. Probably due to exactly what you said.
- secondcoming 4y ago> With that said we don't aim for super senior devs. We're happy to hire a junior, etc. I care much more about the quality of the person than raw experience. Being young and cheap is a good quality, I suppose. Experience is overrated.
- nathan11 4y agoLets be happy when someone says they're hiring juniors. The poster sounds like someone who invests in people and doesn't rule them out based on years of experience on their resume. From all of the "where are the seniors?" threads I've seen, the industry could use more of that.
- dom96 4y agoI have the same impression of Rust: great for software that is well scoped/defined and needs to be stable and efficient, not so much for quick iterations (which for startups is important) and software that doesn't need top performance. I think in general that the Rust hype has outgrown what it's good for. If you're writing a web app in Rust then you may want to ask yourself if you're making the right choice.
- jeroenhd 4y agoFor simple applications, Rust is actually pretty easy to work with in my experience. You don't get a lot of comforts other languages provide, but you don't always need those. The performance difference between a Rust server and other languages are incredible, especially in terms of RAM usage and concurrent connections per second. That said, if your program is going to need tons of entities stored in a database, I wouldn't even consider a language or framework without a solid ORM. Rust has some ORM-lite libraries but I'd end up picking a garbage collected language in practice just because of the difficulties that low level programming bring to such middleware. Iterating in Rust isn't that hard as long as you don't try to cheat your way out. Instead of returning null for methods that you haven't implemented, add a todo!, etcetera. You have to do things somewhat right the first time. I think that's good, because there's nothing as permanent as a temporary proof of concept. You can clone/copy your way out of most annoying Rust restrictions at the cost of performance you'd otherwise sacrifice by picking a higher level language anyway. If your startup doesn't know what it's building, you have bigger problems than the language you choose.
- dom96 4y ago> The performance difference between a Rust server and other languages are incredible, especially in terms of RAM usage and concurrent connections per second. Really depends on what "other languages" are here. If you're comparing against Python then sure, but if you're comparing against Go then the difference isn't that incredible. > That said, if your program is going to need tons of entities stored in a database, I wouldn't even consider a language or framework without a solid ORM. This is actually what I used Rust for recently and honestly the ORM situation is pretty good. The language itself is just too rigid for this kind of work for too little payoff. > If your startup doesn't know what it's building, you have bigger problems than the language you choose. That's true at a high-level, but iterating on small features/changes fast is what makes or breaks most startups.
- bayesian_horse 4y agoHow much more performance do you need to get from Rust over Python (even Cython, PyPy, Numba, etc) to justify the extra development cost? A 2x gain is certainly not worth it. A 10x gain? Maybe. But that is hard to achieve when much of your "compute" is spent on the DB side of things. How many startups actually scale out of needing a few non-db instances?
- adastra22 4y agoRust easily gets 10x improvement in performance over Python in a lot of applications. This is absolutely my experience. A better statement is that it doesn’t get 10x improvement over Go, or other ergonomic compiled languages.
- steveklabnik 4y agoAlso in the context of cloud spend: way way way less RAM, which can translate directly to dollars.
- cozzyd 4y agoYeah, I just wrote a simple daemon in C that had no performance requirements ( listening to a udp socket and dumping stuff into a pgsql db once a minute) because the Python program would use like at least 20x the RAM. When you're running a bunch of things on a resource constrained place (e.g. a single computer that has to do a ton of things sitting on a rack on the Greenland ice sheet), even just the base Python memory usage from a new process adds up...
- ReflectedImage 4y agoIt will be 25x gain on average and your development costs will triple. Is that worth it? Depends on what you are building....
- soggybutter 4y agoMy team helps run and deploy a python service that is entirely CPU bound. It accepts an input, performs some computation, and returns a result without any sort of I/O outside of the initiating HTTP request. In the past week it's averaged around 144 req/s with a p95 latency of ~1s. We average ~80 "instances" to maintain this level of performance. I have very little doubt that, if given the opportunity to rewrite this in rust, we could smash 10x perf improvements. Could we also get more perf out of tuning our python code better? Definitely. Do I think there's 10-20x improvement waiting to be uncovered? No. Unfortunately (fortunately?) we're at a stage that it makes more sense to throw ludicrous sums of money at it than it does to ground up rewrite.
- rozgo 4y agoIn startups and projects where Rust is a premature optimization this makes sense. But, some startups and projects are all about the competitive advantage created by optimizing from day one. In these cases, choosing Rust and other early optimizations is the main enabler of a unique product.
- tegiddrone 4y agoI worked with a shop that wanted to use Rust for their shiny new MVP. And they did... and yes we were not really good at training nor could prioritize/attract rust-experienced devs. The Lead rust dev left due to personal reasons and then we were left with a codebase nobody really had the knowledge/insights to support while rapidly iterating. We smiled and rewrote it in node.js. I think devs get burned when the MVP turns into forever code and somehow are not given room to refactor/rewrite once validated... or they are surrounded by devs who are used to pain/bug-cycle and they (or the business) will accept doing things haphazardly as a cost of doing business. Fred Brook's Second-System effect comes to mind. Ah ha! Rust! Now we HAVE to write good code because rust has so many protections!!
- jeroenhd 4y agoI can't fathom why a company would write code in a language that most of its developers aren't at least somewhat experienced in. If you're writing a program in Rust, hire Rust devs or invest heavily in educating the devs you do have first.
- tijsvd 4y agoNever combine new tech with new functionality. If you want to learn new tech, use it to rewrite an old project that was due anyway. If you want to build new functionality, use tech that you know. This has nothing to do with Rust. I've seen the exact same thing happening with golang in a C++ only environment. Long project, took forever, failed slowly, took a week to rewrite in C++.
- unshavedyak 4y agoSo.. i'm going to disagree, Rust (or any language!) is fine for prototyping. The trick is don't experiment when you're needing to rush a product out. Pick what you and your team is most comfortable in. Avoiding allocations in Rust, on purpose, and being uncomfortable with how to solve design challenges caused by hyper optimizing your code .. is not a Rust problem. Or an any language problem. Rust gave you rope and you hung yourself with it. If you're stubborn and you want to use Rust but aren't familiar with the ways to avoid this; Allocate. Use Arc, Rc, Clone, etc. It won't hurt, it won't be terribly slow, and it almost assuredly won't be slower than your prototype languages. Some might reply "Well then why use Rust!?", to which i would reply because i like it! I love Rust, but if i'm prototyping code i'm not going to write insanely abstract generics either. Why would i? I don't know the problem i'm solving yet, so how can i write truly generic abstractions to solve said problems? Performance is similar. I'll use lifetimes will prototyping in the simple cases, which is most to be honest, but beyond that don't hyper optimize. To summarize: Choose your favorite language at crunch time. Even if your favorite language gives you rope to hang yourself with you probably don't need to.
- dgb23 4y ago> Use Arc, Rc, Clone, etc. It won't hurt, it won't be terribly slow, and it almost assuredly won't be slower than your prototype languages. I very much doubt that. It's likely true for straight up wasteful languages but very unlikely for more optimized runtimes.
- maleldil 4y ago> It's likely true for straight up wasteful languages but very unlikely for more optimized runtimes. What are you comparing it to? I believe parent meant that even if you clone everywhere, your code is still more likely to be faster than Node/Python, and potentially Go/C#/Java. One thing to note is that C++ code tends to allocate all over the place from copy assignment and constructors, and it's still very fast. Rust only forces you to be explicit when cloning, but memcpy is still a fast operation, unless you're cloning large structs.
- 4y ago
- it 4y agoYou can also get match in any variant of Erlang or ML, and those don't force you to jump through hoops for borrow checking.
- david_allison 4y agoAlso Kotlin: `when` or `with...when` for more complex matches
- ParetoOptimal 4y ago> I can't get it why people would prefer to add "?" to everything instead of just having exceptions which automate that behavior. Good question... Maybe... Because with exceptions it's easy to end up with missing cases or unhelpful catch-all exceptions. Typically with optional values I find that this is not the case for some reason. Other interesting links I've yet to consume that may help us get closer to an answer this: https://news.ycombinator.com/item?id=22225170 https://news.ycombinator.com/item?id=22225170 - "You're better off using exceptions" https://softwareengineering.stackexchange.com/questions/405038/result-object-vs-throwing-exceptions https://softwareengineering.stackexchange.com/questions/4050... https://dannyvanheumen.nl/post/why-i-prefer-error-values-over-exceptions/ https://dannyvanheumen.nl/post/why-i-prefer-error-values-ove...
- weavie 4y agoI've been writing Rust professionally for a few years now and if there's one thing I've learned it's that if you ever write a function that takes a parameter of `impl Fn(&Vec<&'a str>) -> &'a str` you are going to be in for some pain. Just make it `impl Fn(&Vec<&str>) -> String`. It is highly unlikely that the extra allocation is ever going to be noticed in the performance. Just because Rust pretty much forces you to be explicit about your allocations doesn't mean you have to avoid them at all costs.
- ModernMech 4y ago> It is highly unlikely that the extra allocation is ever going to be noticed in the performance. I had almost this exact scenario, and yes there is pain in writing it with explicit lifetimes. But I can't agree the performance improvement is negligible; maybe in isolation, but I saw about a 100x speed increase for my application when I switched away from Strings. For me it was because I was doing many of those extra String allocations in a loop, so it killed my performance.
- estebank 4y agoThis is not an uncommon pitfall when working with strings in all languages. In Java for example it is drilled into people to use StringBuilder instead of concatenating with + on String if you do it in a loop, precisely because of this exact issue.
- weavie 4y agoFor sure, optimise when necessary. Rust lets you do this.
- tjdetwiler 4y agoYou can still return the str reference; callers can easily do the copy if they need while allowing for zero-copy for simpler usages.
- estebank 4y agoOne day I need to get around to figuring out how to detect when people are going in circles with lifetime errors and have rustc open https://keepcalmandcallclone.website/ https://keepcalmandcallclone.website/ for them.
- deleted 4y ago[deleted]
- zeroxfe 4y agoIf you're thinking about building something in Rust, a good question to ask is, "what would I use if Rust didn't exist?" If your answer is something like Go or Node.js, then Rust is probably not the right choice. If your answer is C or C++ or something similar, then Rust is very likely the right choice. Obv, there are always exceptions here, but this helps you work through things a bit more objectively. Rust can be a fantastic language for many purposes, but it has a very high development cost.
- richardwhiuk 4y agoNot sure I agree with Go vs Rust. I think if you would choose Java or Python or C#, then Rust might not be the right choice.
- ntonozzi 4y agoGo belongs in the exact same bucket as Java and C#.
- galangalalgol 4y agoC# sure, but unless you are doing something pretty close to the core purpose of some giant java framework java is slow and verbose
- tasubotadas 4y agoSlow and verbose compared to what?
- ntonozzi 4y agoJava, Go and C# (and node) have very similar performance, e.g. https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/.... For all of them, the key to writing high performance code is avoiding allocations and boxing. Go and C# both do this slightly better than Java, but in most domains where these languages are used, this is not a big difference (and this is where you might use C/C++/Rust instead). I've found Go to be more verbose than Java, but I haven't used Go much since generics were released.
- RcouF1uZ4gsC 4y agoQuestion for HN, all things being equal (you are not more familiar with one language/framework) what language would you choose to build a startup in?
- alfalfasprout 4y agoThe one appropriate for what you're trying to build. It may mean multiple languages. Not everything is a CRUD mobile app trying to be the next tinder for cats.
- abledon 4y agotypescript
- distcs 4y agoPython or Go or a mix of both. I have seen new devs with no experience in either get get up to speed quickly in both. For a startup, velocity is critical.
- pjmlp 4y agoJava or .NET platforms, hardly anything else comes close in languages, tooling and libraries.
- JTbane 4y agoAgreed, those are the ecosystems that "just work".
- jeremycarter 4y agoThis is the correct answer. Not the cool answer.
- pjmlp 4y agoMaking a business is not about being cool, unless we are talking about fashion industry.
- secondcoming 4y ago
- ReflectedImage 4y agoIf you are writing high performance code use Rust. (Slow development times, high performance) If you are writing a typical business application use Python. (Fast development times, low performance) Or if you want to be clever do a hybrid of both. Create Rust modules for your Python code. This is just about selecting the right tool for the right job.
- pjmlp 4y agoI would rephrase it as follows, If you are writing high performance code where a tracing GC isn't an option, and there are SDKs available use Rust. Otherwise an AOT compiled language is a better option, and if not, and there are only C and C++ SDKs available, also factor in the development cost of creating wrappers in Rust, before doing the actual development activities. If there is too much money being burned in wrapper libraries, maybe that isn't the best option as well.
- npn 4y agoI picked Crystal so I didn't have to choose.
- ReflectedImage 4y agoThat's in the C / C++ / Rust bucket due to the typing system.
- synergy20 4y agoMaybe nowadays we should all use glue-script + compiled-ffi to iterate fast while keep performance under control? e.g python+cffi, or python+pyo3(for rust), or even lua+capi? do we really need code everything in compiled language these days? the cold path can be dealt with by scripting languages, and let the c/c++/rust/etc to handle the performance critical path instead.
- pjmlp 4y agoNowadays? That is how AOLServer used to be, and all the other scripting languages developed as Apache plugins, back in the 2000's .com wave, like mod_perl and PHP.
- synergy20 4y agoMaybe scripting language was overused down the road? i.e. to use it for everything, and use them like a compiled language(ruby in rails, php framework, django,etc) that made things slow? point here is that to restrict script languages to glue logic for the most part, and always remember to use ffi for heavy lifting, not sure how to balance both yet.
- pjmlp 4y agoThat is why PHP eventually got a JIT, initially thanks to Facebook experiments compiling to C++, and later the JIT proving being capable to generate similar performance. The problem was exactly that overused, without JIT/AOT in the box, with many people shying away from writing native extensions, instead adding more boxes. The difference between doing JavaScript in node with native extensions in 2023, and Perl/TCL with native extensions in 2000, is exactly that, a JIT.
- cneu 4y agoThe main reason why server-side stuff is slow is poor use of the database. Doing e.g. nested loops in a compiled language uses way less CPU than a scripting language, but it should be done in the DB in the first place.
- pjmlp 4y agoReally, unless one needs deployment scenarios where any kind of automatic memory management is not an option, there are several compiled languages with Rust like type systems and much better workflows. Go pick OCaml, Haskell, Scala or Kotlin with GraalVM or OpenJ9, F# with NativeAOT, Swift, Nim, D, whatever.
- rwaksmunski 4y agoI don't know, I haven't had a fight with the compiler in a long while now. On the other hand a $42 dedicated box benchmarked my project's REST API at 270,000req/s. I don't even use a DB, just structs serialized in JSON to a disk and a NAS once every few seconds. One pet IPv6 only server to manage + CloudFlare (Domain, DNS, Cache). Beats today's peak complexity setups, hands down.
- royjacobs 4y agoMy biggest pain point with Rust (in a startup context) is that Rust works really well, until you get to anything related to threading or async. Yes, the claim is "fearless concurrency" but you'll still deadlocking mutexes and once you're heavily into async you need to start using language constructs that feel REALLY awkward, like pinning, runtime checks like RefCell, and so on. IMO if Rust could make that whole aspect of the language more elegant, it'd be much easier to scale up to a larger org.
- dcow 4y agoI honestly think Swift nailed it. Swift's async/await is a pleasure to work with and has the required language/runtime/stdlib support to feel natural and empowering instead of ridiculous and suffocating.
- bryanlarsen 4y agoI disagree, I believe that Rust is a fabulous language for early prototypes. Sure, if you're going to throw away your early prototype there are better languages. But nobody ever does that. Instead your prototype evolves into your product and early expedient decisions you made that were appropriate for a prototype aren't appropriate for your product and you have a significant refactor. And Rust is the best language I have ever encountered for refactoring. Just bang away changing the code until it compiles, and it's quite likely that once it compiles it actually works. That's not an experience I've had in any other language. Usually a significant refactor exposes some foot-guns that don't fire until significantly later. So you avoid refactoring and your code ends up a right mess.
- CharlieDigital 4y ago> I believe that Rust is a fabulous language for early prototypes. The problem is that TypeScript is an even better language for early prototypes. zeroxfe has the right answer: > If your answer is something like Go or Node.js, then Rust is probably not the right choice. > If your answer is C or C++ or something similar, then Rust is very likely the right choice. The only reason one would choose Rust over TypeScript is if one would have chosen C/C++ instead. Then if you need higher perf/throughput: Go, Java, and C# in particular are all options that I'd consider before C/C++ or Rust. C# in particular is highly congruous to TypeScript [0]. JavaScript, TypeScript, and C# have been converging, IMO (and that's a good thing). Seems really natural that if you're a startup finding PMF, start with TypeScript for iteration speed. If you need higher throughput, C# is a stone's throw away from TypeScript syntactically and it's pretty easy to hire for (compared to Rust). [1] Pick Rust if you're building something highly performance and memory sensitive. Pick TypeScript and C#/Go/Java for almost all other cases. [0] https://github.com/CharlieDigital/js-ts-csharp https://github.com/CharlieDigital/js-ts-csharp [1] https://raw.githubusercontent.com/CharlieDigital/js-ts-csharp/main/js-ts-csharp.png https://raw.githubusercontent.com/CharlieDigital/js-ts-cshar...
- packetlost 4y agoI think it depends on what you're doing. I'd argue statically typed Python (ie. with type hints) is also good for an early-prototype language and has the benefit of being able to swap out parts at a time via C FFI with Rust or something like PyO3. Pypy with asyncio (so FastAPI?) is what I'd choose for a web framework these days, personally.
- throwawaygal7 4y agoPeople who are really interested in rust tend to be top-tier developers. I don't think they're consciously lying about their experiences working with the language but they may not hit the speed bumps that normal people would. My personal abilities make me competent in golang, ruby, python, java, c++. I love the quasi-functional styling of rust but whenever I've tried to build small projects in it I've gotten bogged down in fighting with the compiler in ways I never do in the former. It is fast as all get out tho!
- throwawaygal7 4y agoDie hard rust fans often minimize the very real developer difficulty incurred by their language of choice. Even major library maintainers in rust have criticisms of various language features because of their difficulty to use. These are real and substantiative concerns that would affect any development team not made of expert rustaceans. Just look at basic dynamic programming implementations in a normal language versus rust for say popular leap code questions and you'll see the difference in basic developer productivity.
- steveklabnik 4y agoOxide is a startup and we use Rust for everything except the front end of websites (where we use TypeScript.) In some cases that’s due to hard requirements (embedded) but we use it for web backend cases as well. Iteration time hasn’t been an issue, but compile times can be annoying. Though obviously compile time is related to iteration time. Of course, all of these things are anecdotal. Collecting anecdotes is how you develop evidence, of course…
- badrequest 4y agoSteve, I just want to say I like you a lot. :)
- steveklabnik 4y agoThanks, that's very kind.
- ThatGeoGuy 4y agoTangram Vision [0] is also a startup and we also use Rust. We're using it to develop robotic / autonomous sensor calibration tools that would normally be written in a variety of C / C++ libraries. For context: most if not all of our team has developed calibration tooling similar to what we're doing now in the past, just at different startups and very specific to certain robotic or sensing configurations. If anything, once we got CI sorted and started using our own internal registry I would argue that we are significantly faster in terms of iteration time. This is partly because the team is small, but also because most of our tooling is consistent and easy to keep in lockstep. Pulling libraries is done uniformly across platforms and architectures, and our CI runs (through GitLab) stay up-to-date with the latest tooling without issue. Having a stronger type system to detect errors early and a compiler that actually tries to give human-readable messages (looking at you C++ linker errors) using that type system makes everything so much easier. Compile time seems like it would be an obvious bit that slows one down, but in practice sccache [1] does what it ought to and we barely notice it (at least, I don't and I haven't seen team members complaining about build times). Mostly I'd argue that the real thing holding us back is tooling extant to the rest of the wider Rust ecosystem. Debugging and perf tools are great in Unix land, but if you're making anything cross-platform you need to know more than just perf. That might just be my opinion though, I'll admit I'm still learning how best to apply BPF-based tooling even in Linux alone. I also realize I'm responding to steveklabnik, so I suspect most of what I'm saying is well-known and that this comment is really more directed at TFA. [0] https://tangramvision.com https://tangramvision.com [1] https://github.com/mozilla/sccache https://github.com/mozilla/sccache
- rdtsc 4y agoIt's great when wanting to play with cool new technology combines with implementing a viable product to sell to customers. But those two things don't necessarily go together. Quite often they are at odds with each other, and then you have to pick one or the other: either we spend resources playing with cool technology, or deliver a product customers will buy. Neither is wrong if it's your own resources, it's just important to understand that there is a trade-off involved.
- dcow 4y agoExactly. "Rust wasn't the right choice because we spent too much time and resources playing with it." is not an argument against Rust. It's an argument against learning a new technology while looking for PMF. There's nothing inherent about Rust that makes it a poor choice to build a first iteration of a product with.
- mamcx 4y ago> Perf is easy when you have AWS credits. One reason that you might pick Rust is for overall performance. Interesting: Rust save money but that mean effort!
- marcosdumay 4y agoEven on the cloud, Rust will only save you money if you have enough users. But the effort is upfront. Unfortunately, the cloud isn't a very good environment for mixed-languages deployments (unless you stick to the most basic services), so you have to make a decision on the very beginning and stay with it.
- jakswa 4y agoI remember reading about PropelAuth somewhere and thinking that Rust might slow down development -- something I wanted to be proven wrong about since I've been learning rust off and on, and like some things about it. It seems it's ending up up a mixed bag, and the negatives in the bag are still light enough that you're carrying it forward. Thank you for this blog post!
- dhbradshaw 4y agoWe have a fairly complex app with a front end in Typescript and a back end in Rust backed by Postgres on AWS. My favorite part of the job is coding in Rust and we do a lot of cool things in that backend code. Unfortunately, most often the Rust code is the fastest and easiest part of a change, which means that I spend most of my time solving problems either on the front end with Typescript or on CI and infra type things rather than the Rust part. It's a bit sad: if something just works, you spend less time on it than on the hairier things.
- EVa5I7bHFq9mnYK 4y agoBackend code is simpler because is has two limited well defined surfaces (API for the frontend on one side and database on the other side). Frontend is harder because it has to interface with those impolite hairy meat creatures ...
- dcow 4y agoFrontend code has two as well: the input methods (mouse, keyboard, screen) and the API surface. > Backend code is simpler I hear this every once in awhile and think it's mostly a front end happy hour misrepresentation that makes everyone feel good so it gets repeated. The service layer of an application is very often far more complicated than, or to be fair, at least as complicated as, the user interface. Front end devs just typically aren't good at chopping up their problem into nice interfaces and therefore struggle to test it reliably or make large broad changes efficiently. This is where the complexity comes in. That's not a stab at FE devs, it's just not a skill that often gets rewarded in FE work so it's not very prevalent, which I find sad. The service layer has to deal with enforcing the correctness of business logic despite the infinite ways the meat monkeys can interact with it. It does this by defining clear boundaries on the outside and by ensuring the transactional correctness of logic on the inside. While front end folks have to figure out the correct UX to use to successfully communicate with with a user, service layer folks have to figure out all the implications of a single action the user wishes to take and make sure it happens correctly. Data validation, data modeling, transactions, errors, queuing, retries, scaling, monitoring, etc. are all things that would probably make the average FE dev explode if thrust upon them.
- jmull 4y agoSince safety was the first reason given for using rust, I'll just point out: There are other safe languages. I think it's a really useful thing to have from day one, but it doesn't particularly point you to rust. Also, performance is really about learning what your bottle-necks are, profiling them and optimizing them. You probably have no idea what those are when you start, so it's not really the right time to try to solve it. (There's a decent chance, e.g., that your inner loops won't even be in code you write, like the database.) Probably the best thing you can do for long-term performance up-front is to try to stay flexible, and try to keep your architecture simple.
- ReflectedImage 4y agoRust does a bit more on the safety front than typical programming languages.
- jmull 4y agoThere’s Javascript/Typescript.
- dcow 4y agoReally? I guess if your typical programming languages are C and C++. Otherwise Rust just has semantics that allow more control over memory, as is often needed in lower level programs, while preventing pointer aliasing. The majority of languages in existence are memory safe--some even more so than Rust. They're just not as flexible.
- ReflectedImage 4y agoIt's much better than Java, Kotlin and C#. The borrow checker detects the majority (~95%) of concurrency problems. We don't have that many single core CPUs lying around anymore. It's got a story on high performance, high concurrency programs which is significantly better than anything else I've seen so far.
- dcow 4y ago
- estebank 4y agoI find it surprising that so many people are arguing about the benefits and drawbacks of `?`, when in my experience the handling of Result and Option haven't been an issue in practice on the consuming side (`?`, `.unwrap()`, `.map()`, `.ok()`, if let, match, let chains, let else, etc. help a lot), but where all the pain comes from is having to declare the appropriate error type itself. Libraries like `anyhow` takes some of the pain away, but declaring an appropriate struct or particularly an enum in the right places, and the boilerplate for all the type conversions (From/Into impls) are where, during development, I have frustration. What I do then is either use Result<T, ()> or a single `struct Error(String);`, and go back once I have all the scaffolding in place and pry the implicit error tree back into the type system. Anonymous enums like typescript (`A | B | C`) could presumably help here.
- a5huynh 4y agoI've run into similar issues and found that the `thiserror` crate (https://crates.io/crates/thiserror https://crates.io/crates/thiserror) combined w/ anyhow makes a lot of that pain go away
- steveklabnik 4y agoFor those reading this that aren't super familiar, common Rust advice is "use thiserror for libraries and anyhow for applications," as they make slightly different tradeoffs and so are useful, especially together.
- chrisgacsal 4y agoI would add `snafu`(https://crates.io/crates/snafu https://crates.io/crates/snafu) here as a good alternative to thiserror+anyhow.
- echelon 4y ago`anyhow` + `?` make writing an application as smooth as butter. You won't miss exceptions. Don't use `anyhow` for libraries, though. You want to provide your consumers the ability to `match`.
- Ylmaz 4y agoI like this quote from 'The art of Unix Programming' published in 2003 "While it still makes sense to write system programs and time-critical kernels of applications in C or C++, the world has changed a great deal since these languages came to prominence in the 1980s. In 2003, processors are a thousand times faster, memories are a thousand times larger, and disks are a factor of ten thousand larger, for roughly constant dollars. These plunging costs change the economics of programming in a fundamental way. Under most circumstances it no longer makes sense to try to be as sparing of machine resources as C permits. Instead, the economically optimal choice is to minimize debugging time and maximize the long-term maintainability of the code by human beings. Most sorts of implementation (including application prototyping) are therefore better served by the newer generation of interpreted and scripting languages. This transition exactly parallels the conditions that, last time around the wheel, led to the rise of C/C++ and the eclipse of assembler programming."
- apozem 4y agoThat's a great way of looking at it. Languages all have benefits and drawbacks, but you have to consider whether they help you for your problem. One time, I met a guy who wrote firmware for Seagate hard drives. Any new feature he added had a budget measured in microseconds. Obviously he wrote nothing but C++.
- dilippkumar 4y agoIn a benchmark of how many fortune responses are returned by various web frameworks[0], nodejs returned 80k odd fortunes per second. The fastest c++ framework compared here returned 616k odd fortunes per second. Assuming that my application scales by the same amount (big assumption, yes), I could cut AWS costs by 7.7 times (!!!) by using the C++ implementation. I'm pretty sure that maintaining a C++ codebase is less than 7.7 times more expensive than Node, even if you throw in extra development time etc. This also ignores the decades worth of excellent tooling we've built up for C++ (static analyzers, fuzzers, etc). At a startup, when building things fast matters more than costs, sure. I buy the argument for Node or Python or any other interpreted backend. But once you start to scale, things change after some threshold. Unless you're facebook[1]. [0]. https://www.techempower.com/benchmarks/#section=data-r21 https://www.techempower.com/benchmarks/#section=data-r21 [1]. https://developers.facebook.com/blog/post/2010/02/02/hiphop-for-php--move-fast/ https://developers.facebook.com/blog/post/2010/02/02/hiphop-...
- kilgnad 4y agoRust is weird. It has high level features that make is superior to high level languages like go and python. But the low level features like default move semantics inevitably make it harder. IMO there is merit in making a language that is equivalent to garbage collected rust by default with ownership rules similar to python. Then the classic rust based ownership and allocation schemes are all opt-in syntax-wise in the same way Box is opt-in.
- frodowtf 4y agoThe reason why people would like to pick Rust is because of its ergonomic features like sum types, streams and of course the toolchain. But here is a claim: Most business-level programmers are not ready for dealing with the borrowing and ownership concept. They don't want to care about reference vs. value types. They can't do memory management efficiently, because most of them have never used a language without GC. With Rust you would need to care more about memory which is not necessary for most use cases in startups.
- dcow 4y agoI don't agree. I think the author is conflating two things: 1. learning Rust, and 2. using Rust. If you take away "Rust made us slow because our team had to learn how to use it and thus we had slow iterations and it's harder to find hires with Rust knowledge" from the equation, then you aren't left with much argument against using Rust early. The iteration time issue with Rust is solved by experience. We use Rust and our iteration times are average. What we gain is not performance, that's not a reason we use Rust (for an early stage startup, totally agree you burn credits until you can afford to care). We gain correctness. And at an early stage, correctness without paying for a massive QA team is a huge boon. There are definitely more mature tools for quickly standing up CRUD APIs. If you want a framework that can bootstrap you into an OpenAPI with docgen, swagger, all the bells and whistles, Rust doesn't do that. But Rust will help force you to write correct code that never crashes and handles edge cases it's easy to forget about when moving fast in a duck typed language. The only language we seriously considered over Rust was Swift. But Swift's just wasn't quite there yet. It might be today. If I was starting something from ground zero today, I'd probably lean towards Swift and need to be argued down back to Rust or Python.
- ReflectedImage 4y agoWell Python code will on average will be more correct than Rust code. I'm not sure why you feel Rust code would be more correct than Python code but it certainly isn't true.
- tcfhgj 4y agoI strongly believe that if I would code anything significant my Rust could would be more correct. The reasons are types and rusts multi threading guarantees, which become even more helpful when doing refactorings
- ReflectedImage 4y agoIt won't because the number #1 factor in bugs is the number of lines. The Python code will be significantly shorter and thus contain less bugs.
- alfor 4y agoPerformance of language is almost never a big concern, but it’s so interesting for a technical person.
- hardwaregeek 4y agoI write a lot of Rust. I think you can do a startup in rust but you need to explicitly go against the natural inclinations of rust. Rust is a great language partially because it cares about the details. It’ll do stuff like distinguish between Path and String because it treats the edgecases as important. In a startup that’s not really a priority. In fact focusing on edgecases and doing things the “right” way is completely not the point of writing code in a startup. Rust is also a great language to refactor, something that’s also not ideal for a startup to be spending cycles on. Would I do a startup in rust? Maybe. It’d depend on the idea. But I’d take measures to avoid the natural orthodoxy of Rust.
- Aissen 4y agoCrazy to think that cloud credits, in addition to distorting the hosting competition, might also distort the language choice competition…
- ReflectedImage 4y agoThe first hit of cloud is free but once they have you hooked they charge an arm and a leg afterwards.
- dmillar 4y agoPerhaps not the case here, but there are a couple of things I would add to this sentiment. First, if you love Rust uniquely, I'd argue it might still make sense to use Rust to build your first product iterations. If your initial team commonly loves Rust, and can't agree on "love" for another common language, perhaps Rust is the best language. Burnout will happen exponentially faster if developers are lamenting the language (n.b. Rust is commonly lamented). I think there are enough language/platform options these days for this to be an unlikely scenario, but this is to say don't discount your passion for a language because it doesn't iterate fast enough. Second, if the problem your startup is trying to solve is solidly in the performance and security realm, it makes sense to start in Rust. If your pitch is something like "pandas but fast and memory efficient" it also makes sense to start your project in something like Rust.
- andrewstuart 4y ago"I find myself missing match in pretty much every other language I go to." Python has match, is this the same thing? https://blog.teclado.com/python-match-case/ https://blog.teclado.com/python-match-case/
- shmerl 4y agoThat has a catch 22. If you aren't going to start with Rust from the beginning, switching to it later becomes too costly and too difficult, which defeats the argument of it being useful in general. Most often what's used in the beginning as "prototyping" is cemented into the system to the point that it's hard to change it. So yeah, better to deal with complexities in the beginning and save on switching later, than not to use it all.
- japhib 4y agoFor pattern matching and expressiveness in a backend language that lets you iterate quickly, I'd highly recommend Elixir.
- innocentoldguy 4y agoI would reach for Elixir, Phoenix, and LiveView for any new web development. We were using Java before and were running into major productivity issues. After extensive testing with Elixir, Node, Clojure, Go, and a handful of other languages, Elixir won out, we rewrote our entire stack, and our productivity skyrocketed. I can’t say enough good about it.
- mixmastamyk 4y agoYes, many times "typing supremacists" and pedantic folks will recommend this course of action but it is not a great idea much of the time as the piece illustrates. Getting things perfect on a code-level up front is rarely what a new project needs. A more effective strategy for business is to instead prototype in something like Python—that's what it's for. This was known back in the 90s, and been somewhat forgotten. Django too. Like a flexible clay to rapidly sculpt to a first approximation. Then: 1) Get to product market fit, keep iterating until you do. Do not go to step 2 until that happens. 2) Get the fundamental data models right, get your fundamental software design right. Keep iterating until you do. Do not go to step 3 until that happens. This stuff is easier in Python as it gets out of your way. Yes use pyflakes, a few tests, and a code formatter to keep you honest. But not much more that that. Pycharm for example, if you need a helping hand. 3) When step 1 and 2 are a looking good, then rebuild the foundation of your gleaming skyscraper with the steel girders of rust, java, and/or other bdsm languages with an already good product and design. Step three may not even be needed if you have a CRUDdy project. Complete the typing at that time.
- eYrKEC2 4y agoWe love using rust on the backend at https://mayhem4api.forallsecure.com/ https://mayhem4api.forallsecure.com/ and in our CLI. If I were the decider, I'd choose it again. Rust is a hurdle to learn, but the confidence you gain from the type system is fantastic. I've worked in other projects with different, looser-type'd languages (no names! no flames!) and despite good testing coverage, the confidence on release to prod is not as high.
- AceJohnny2 4y ago> Perf is easy when you have AWS credits. I get that the point of this article is that launching > sustaining. But I have a horror story about AWS credits for startups: a friend's startup got their account suspended for a couple days when their Credits ran out, they started getting billed 5 digits (as they expected), and Amazon's fraud detection detected this as an anomalous billing pattern and suspended them! For transitioning from AWS credits to billing!? Considering all their operations were running in AWS, and they were providing a HW-critical service to their customers, it was bad. This was late last year. This was despite getting reassurances from their AWS rep that the transition would be smooth.
- ISL 4y agoIf those reassurances are in unmistakable writing, a letter from the startup's corporate attorney may yield a quick refund and compensation.
- AceJohnny2 4y agoSure, but in the life of a startup that's just one extra thing they'd rather not have to deal with, and the damage isn't just financial.
- legerdemain 4y agoIn my experience with Palantir "alums," none of the crotchety perfectionists I knew ended up working with Rust after leaving. I guess AI (as the author of this post is affectionately known) beat the trend by starting his own company!
- twsted 4y ago"Building a startup in Rust". I know the hype around Rust, but this is really exaggerated: you build a startup for creating a product or giving a service, not to have something written in Rust. Your customers should care about what you are offering, much more than about which language do you use.
- julianeon 4y agoI find it mystifying that one of the reasons you can supposedly pass over Rust, and avoid performance concerns, is to "take the free money." Literally. That is, the free money, in credits, that allows you to not worry about performance for a while. The obvious problem being... "What happens when the free money runs out?" It's not addressed, but the implied answer seems to be "Well, by then it'll be six months later, and..." And? And what? It's still a problem! It didn't go away. The money deflected the perf concerns for some time, maybe a year - but then it's back, bigger and badder than ever. Rust solves that by not requiring that outlay ever, by being more efficient. Seems like a very poor reason to not choose Rust, to me.
- globalreset 4y agoAt that point startup has revenue so can pay or is dead so it doesn't matter.
- nazka 4y agoI am a Rust fanboy but using it to start a startup hmm unless it’s for a specific use case. No. Why? Because the biggest bill you will have to pay at first in a startup and for a long time won’t be AWS but all the (devs) salaries. And compare to what you will pay to AWS that’s a lot of money. So a gain in performance won’t matter as much as in your success (and survivability) than speed in developing new feature every week. Depending what you do but it’s usually the case that performance won’t matter until mid late game. I saw a startup at +300M valuation still not having to worry about performance for a long time. And a cut in the AWS bill thanks to using a more performant language like Rust won’t make that much a difference compare to how much they had to pay devs. So you just want a language where you can ship features fast. Also the hiring pool is still very small.
- cultofmetatron 4y agoReading this makes me reaffirm my decision to build my startup in elixir. At the time, it came down to 3 compelling choices 1. typescript - I already had 6 years of full stack js experience. The ecosystemis full of issues but its all issues I'm used to. 2. rust - new kid on the block. the type system and speed were compelling but it was still being developed and the learning curve was brutal. Plus I was under the gun to get the mvp up. we needed to get a working piece of software up and test out business assumptions. In the end I went with elixir. Realtime sync was a huge killer feature we were aiming for and phoenix came with the best out of the box support for it. Overall productivity was on par with javascript while the functional aspects made certain types of bugs non issues in elixir. runtime performance has been more that adequate. after 3 years in production, we have only recently rolled out rate limiting and caching and only as a precaution as we've been expanding quickly. Echoing the author's sentiments, I can definitely see places where rust could be better and thanks to tools like rustler, we'll be able to bring those in piecemeal as needed. I'm sure our product would be even faster and more efficient on resources if we did it in rust but I'm pretty sure we would have more likely run out of runway before that happenned.
- Matthias247 4y ago> We have extractors for different user requirements to make adding APIs very straightforward. We have middleware for scoping requests per customer. In most languages, this is pretty standard, but in Rust, for our use case, they both require at least a rough understanding of pinning. This is more about "async Rust" and the way that the most common web frameworks for Rust are utilizing it. It should be totally possible to write much easier to understand frameworks and code - potentially with the limitation of using a classical thread per request architecture which avoids most of the async/lifetime/pinning pitfalls. The main drawback seems that such frameworks seem out of favor in Rust and thereby not available or not very well maintained.
- jeremychone 4y agoWell, we are doing just that, building a new venture with Rust because we think it is transformative in our field. Will post our findings in a year or so.
- aman262 4y agoI don't understand the rust fandom. You probably just don't need it.