[HN Gopher] I love building a startup in Rust but wouldn't pick ...
       ___________________________________________________________________
        
       I love building a startup in Rust but wouldn't pick it again
        
       Author : aisrael
       Score  : 197 points
       Date   : 2023-02-17 15:21 UTC (7 hours ago)
        
 (HTM) web link (www.propelauth.com)
 (TXT) w3m dump (www.propelauth.com)
        
       | eYrKEC2 wrote:
       | We love using rust on the backend at
       | 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 wrote:
       | > _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 wrote:
         | If those reassurances are in unmistakable writing, a letter
         | from the startup's corporate attorney may yield a quick refund
         | and compensation.
        
           | AceJohnny2 wrote:
           | Sure, 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.
        
       | TuringTest wrote:
       | Rust 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.
        
         | drdaeman wrote:
         | Well, I had some difficulties writing a tiny init program for a
         | container because process and signal handling are currently in
         | a pretty weird place in Rust.
        
         | rrishi wrote:
         | I think if you've captured the essence of the discussion on the
         | usability of Rust really well.
        
       | rattray wrote:
       | This 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).
        
         | dochtman wrote:
         | N = 1, but at startup scale we have definitely not had a hard
         | time hiring skilled Rust devs. Just go on /r/rust and advertise
         | your (non-crypto) job and get a lot of inbound.
         | 
         | (We were specifically looking for remote folks near EU time
         | zones, maybe local in SF is harder?)
        
         | rozgo wrote:
         | 6mo+ 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 wrote:
         | > 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 wrote:
           | > 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.
        
             | unshavedyak wrote:
             | Well, hiring only super experienced people in a niche
             | talent pool feels arbitrarily difficult. Young devs can be
             | just as good, and we all need to build experience somehow.
             | 
             | One rule of thumb for me is that the more young a developer
             | we hire is, proportionally we also need to hire an equally
             | senior. Ie we don't want a huge amount of developers
             | lacking experience.
             | 
             | However if you have enough senior developers to mentor the
             | young ones? Seems a net win for all involved, to me at
             | least.
        
             | nathan11 wrote:
             | Lets 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.
        
             | alfalfasprout wrote:
             | > Being young and cheap is a good quality, I suppose.
             | Experience is overrated It's "overrated" until it isn't.
             | And then you learn very, very expensive mistakes.
             | Unfortunately it takes experience to learn why this
             | viewpoint is nothing more than hubris.
        
       | ReflectedImage wrote:
       | If 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.
        
         | npn wrote:
         | I picked Crystal so I didn't have to choose.
        
           | ReflectedImage wrote:
           | That's in the C / C++ / Rust bucket due to the typing system.
        
         | pjmlp wrote:
         | I 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.
        
       | dmillar wrote:
       | Perhaps 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.
        
       | synergy20 wrote:
       | Maybe 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 wrote:
         | Nowadays?
         | 
         | 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 wrote:
           | Maybe 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 wrote:
             | That 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 wrote:
             | The 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.
        
       | dcow wrote:
       | I 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 wrote:
         | Well 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 wrote:
           | I 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
        
           | dcow wrote:
           | Curious: have you written Rust in a serious capacity before?
        
         | Sodman wrote:
         | The author touches on why it matters in the article - either
         | you have to restrict hiring to folks who are already rust
         | experts (much smaller hiring pool, also usually meaning higher
         | comp expectations) - or you have to consider the cost of
         | training new/existing staff on Rust. Rust has a notoriously
         | difficult learning curve, especially to folks who don't have a
         | background in C/C++. As the author mentions, you may be looking
         | at 6+ month ramp up time until new hires can comfortably write
         | non-throwaway tech-debt free production code. For many startups
         | looking to iterate quickly, that's just too slow.
         | 
         | Conversely if you are looking to hire Java folks, you'll have
         | an enormous pool to pick from, or if you need to train somebody
         | in eg Go - you can do that significantly quicker than you could
         | with Rust.
        
           | dcow wrote:
           | I was putting that argument aside because that's an argument
           | you can make for any language and it changes depending on who
           | you know, what circles you're in, etc. It's and externality
           | not specific to Rust. You can say the same for Erlang, or
           | Swift, or C#, or ...insert language that isn't JavaScript.
           | 
           | What I'm saying is that, disregarding the externalities, I've
           | found Rust to be quite a boon and not _inherently_ a bad fit
           | for an early stage. YMMV.
        
       | julianeon wrote:
       | I 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 wrote:
         | At that point startup has revenue so can pay or is dead so it
         | doesn't matter.
        
       | dom96 wrote:
       | I 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 wrote:
         | For 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 wrote:
           | > 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.
        
         | tcfhgj wrote:
         | > If you're writing a web app in Rust then you may want to ask
         | yourself if you're making the right choice.
         | 
         | ok, I did ask myself this, still going with Rust there ;-)
        
       | japhib wrote:
       | For pattern matching and expressiveness in a backend language
       | that lets you iterate quickly, I'd highly recommend Elixir.
        
         | innocentoldguy wrote:
         | I 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.
        
       | twsted wrote:
       | "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.
        
       | kilgnad wrote:
       | Rust 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.
        
       | cultofmetatron wrote:
       | Reading 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.
        
       | pjmlp wrote:
       | Really, 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.
        
       | mixmastamyk wrote:
       | Yes, 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.
        
       | bayesian_horse wrote:
       | How 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?
        
         | soggybutter wrote:
         | My 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.
        
         | adastra22 wrote:
         | Rust 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 wrote:
           | Also in the context of cloud spend: way way way less RAM,
           | which can translate directly to dollars.
        
         | ReflectedImage wrote:
         | It will be 25x gain on average and your development costs will
         | triple. Is that worth it? Depends on what you are building....
        
       | rwaksmunski wrote:
       | I 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.
        
       | rozgo wrote:
       | In 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.
        
       | rdtsc wrote:
       | It'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 wrote:
         | Exactly. "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.
        
       | tegiddrone wrote:
       | I 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!!
        
         | tijsvd wrote:
         | Never 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++.
        
         | jeroenhd wrote:
         | I 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.
        
       | hardwaregeek wrote:
       | I 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.
        
       | unshavedyak wrote:
       | So.. 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 wrote:
         | > 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 wrote:
           | > 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.
        
             | dgb23 wrote:
             | > your code is still more likely to be faster than
             | Node/Python, and potentially Go/C#/Java
             | 
             | Python very likely, Node probably too, not sure. I doubt
             | it's true for the others. My guess is you're going to use
             | less resources (memory etc.) but you're not going to beat
             | their runtimes with hand-rolled GC (ref counting) and
             | allocations all over the place.
        
               | unshavedyak wrote:
               | Really depends on what you're doing.
               | 
               | The thing is if you know enough about why cloning is slow
               | - like a really fat string or a tight loop - you probably
               | also know enough to avoid that. At least in my
               | experience.
               | 
               | There's a ton of rope in Rust with lifetimes, generics,
               | etc. Most if not all generic bounds have implications
               | about the user and caller. Choosing which type of methods
               | you use to avoid allocation while prototyping can be
               | exceptionally difficult to do and be correct.
               | 
               | Refcounting is not that bad imo, and is very very easy.
               | The moment you're at "well we need to beat the
               | performance of X" is probably when you can make
               | better/intelligent decisions about how you allocate,
               | whether to use Arena/Bump/etc.
               | 
               | Also, if you wanted to be in Go/C#/etc you just would.
               | You're using Rust (in this discussion) because you wanted
               | to. When performance is a concern, you can deal with it -
               | but the basic allocation tricks (Arc/etc) don't represent
               | such a significant performance loss that suddenly your
               | Prototype no longer functions.
        
               | dgb23 wrote:
               | Right, I missed the broader point. When you choose to use
               | Rust but need to advance quickly, you are going to be
               | fine with some of these techniques.
        
       | jmull wrote:
       | Since 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 wrote:
         | Rust does a bit more on the safety front than typical
         | programming languages.
        
           | dcow wrote:
           | Really? 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 wrote:
             | It'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 wrote:
               | I'll give you that.
               | 
               | The reason I questioned is because in my experience with
               | those languages the 95% problem is not the actual data
               | consistency rather it's locking and synchronization hell
               | that results from needing to make your program threadsafe
               | to ensure data consistency. Rust says, don't get yourself
               | in a situations where you need to do that in the first
               | place, it's not safe. Just clone the data or leak it read
               | only or Cow it.
               | 
               | What Rust does is great, it sets you up so you're never
               | sharing references across threads unless you try really
               | really hard. And that's the source of needing manual
               | synchronization the majority of the time. However, when
               | you do need locks, Rust doesn't do anything to help. In
               | other words, if you copied a Java program to Rust with
               | object instance pointers all over the place, I bet it
               | would feel just as bad in Rust.
               | 
               | So I tend to think of that more as "thread safety" than
               | "memory safety". But we might just be arguing semantics
               | at this point. I agree Rust is far more of a pleasure to
               | work in than Java and C#.
        
       | royjacobs wrote:
       | My 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 wrote:
         | I 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.
        
       | Aissen wrote:
       | Crazy to think that cloud credits, in addition to distorting the
       | hosting competition, might also distort the language choice
       | competition...
        
         | ReflectedImage wrote:
         | The first hit of cloud is free but once they have you hooked
         | they charge an arm and a leg afterwards.
        
       | ParetoOptimal wrote:
       | > 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 - "You're better
       | off using exceptions"
       | 
       | https://softwareengineering.stackexchange.com/questions/4050...
       | 
       | https://dannyvanheumen.nl/post/why-i-prefer-error-values-ove...
        
       | legerdemain wrote:
       | In 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!
        
       | andrewstuart wrote:
       | "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/
        
       | weavie wrote:
       | I'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.
        
         | jossclimb wrote:
         | A lot of programmers will look at '`impl Fn(&Vec<&'a str>) ->
         | &'a str`' and think what the hell is that, alien hieroglyphics?
        
         | ModernMech wrote:
         | > 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 wrote:
           | This 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 wrote:
           | For sure, optimise when necessary. Rust lets you do this.
        
         | estebank wrote:
         | One 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/ for them.
        
         | tjdetwiler wrote:
         | You can still return the str reference; callers can easily do
         | the copy if they need while allowing for zero-copy for simpler
         | usages.
        
         | BaculumMeumEst wrote:
         | [flagged]
        
           | bruce343434 wrote:
           | thanks for running this through chatgpt for me
        
             | BaculumMeumEst wrote:
             | Hacker News has never allowed bots or generated responses
             | on the platform. All content posted on Hacker News should
             | be generated by humans, and any form of automated or
             | algorithmic content creation is not allowed. This policy is
             | in place to ensure that the content on the platform is of
             | high quality and relevant to the community.
             | 
             | Edit: Please stop downvoting me. I'm trying to contribute
             | to the discussion, and I think my perspective is valuable.
        
       | bryanlarsen wrote:
       | I 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.
        
         | mike_hearn wrote:
         | Have you tried something like Kotlin? It has the same
         | experience IMO of being very easy to refactor, especially
         | because the IDE can do so many refactorings for you very fast,
         | and because the compile turnaround time is so low.
        
         | jay-barronville wrote:
         | > _Sure, if you 're going to throw away your early prototype
         | there are better languages. But nobody ever does that._
         | 
         | You can't be serious. I've seen prototypes get thrown away all
         | the time, _especially_ at startups. In fact, I'd say that's
         | more common than not.
        
         | hinkley wrote:
         | One of the things I've vowed to do for my next interview cycle
         | is set myself up an empty project with test, and it is
         | appalling how many interviewers assume that implementation
         | without any tests is something a senior developer won't simply
         | laugh at the suggestion and leave the room.
         | 
         | It takes too long to do these basic steps and then copy them to
         | new projects. And generators only work once, if then, which
         | means they are most useful in languages that have stopped
         | iterating, which is not that compelling.
         | 
         | I'm hoping the next version control system solves the rerere
         | problem and we can build our projects by forking a template
         | project, then pull commits from upstream as necessary.
        
           | Sodman wrote:
           | You have to remember though that coding interviews !=
           | production code. Taken to the extreme, are you also adding
           | logging, metrics, performance benchmarks, etc?
           | 
           | TDD is great if you can get it working in a tight interview
           | time schedule - they can also reveal any misunderstandings of
           | requirements before the actual solution is implemented!
           | 
           | On the flip side however, many interviewers have experienced
           | countless folks who spend the majority of the interview time
           | on tests and setup, only to run out of time on delivering the
           | solution to the actual presented problem. When I feel like
           | somebody's spending too long on these things I'll try to
           | nudge them towards wrapping up the tests and moving onto the
           | solution. You would be surprised though by just how
           | frequently it's met with open hostility, by candidates with
           | only 10-15 mins left in an hour-long interview and no
           | solution started!
        
             | hinkley wrote:
             | And in a real situation I have all of these tools set up
             | and running, so I shouldn't need to spend more than a
             | minute faffing about with them. I'm just writing
             | exploratory tests to make sure that I've got the bits right
             | before I put them together. Even in an hour task those
             | tools can be a force multiplier, once you figure out how to
             | make them work instead of fighting them constantly.
             | 
             | What's happening in interview loops is that we're
             | implicitly or explicitly selecting for people who prefer to
             | YOLO instead of writing tests, and then we are surprised
             | how hard it is to get new and existing hires on board with
             | mature testing processes. The people you need don't work
             | here, they work somewhere else.
        
         | crispinb wrote:
         | > But nobody ever does that.
         | 
         | Please don't report your own experience samples as plain
         | universal facts. It is one of the more common means by which
         | falsehoods spread. I have no doubt that's not your intention,
         | and you believe what you write, but you cannot have a basis for
         | such a bald statement, and it happens to be false.
         | 
         | I have seen prototypes built and discarded very frequently.
         | Indeed in an earlier incarnation it was my own professional
         | focus.
         | 
         | I have no idea how common it is in your country, or globally,
         | or in specific industrial sectors. Usable stats in tech are
         | hard to come by (in large part because of its ubiquity). But
         | your statement is just false, and commonly repeated.
        
         | CharlieDigital wrote:
         | > 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
         | 
         | [1] https://raw.githubusercontent.com/CharlieDigital/js-ts-
         | cshar...
        
           | packetlost wrote:
           | I 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.
        
             | CharlieDigital wrote:
             | I agree; Python is a great choice especially if whatever
             | you're building is heavy in math and/or ML. The ecosystem
             | is just better so it makes sense then to build your backend
             | stack with Python.
        
       | throwawaygal7 wrote:
       | People 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!
        
       | PaulHoule wrote:
       | I 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.
        
         | User23 wrote:
         | Exceptions 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 wrote:
           | What 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.
        
         | adamnemecek wrote:
         | They 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 wrote:
           | That's C++. It puts the C in Cthulhu.
        
           | saurik wrote:
           | That'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 wrote:
             | > 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.
        
         | taeric wrote:
         | > 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 wrote:
         | Exceptions 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.
        
         | flohofwoe wrote:
         | The 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 wrote:
           | Exceptions 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.
        
             | jstimpfle wrote:
             | If 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.
        
             | vore wrote:
             | I 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.
        
           | kcartlidge wrote:
           | My two main languages are C# and Go.
           | 
           | * C# uses exceptions, and when I code it feels exactly the
           | right choice
           | 
           | * Go uses error return values, and when I code it feels
           | exactly the right choice
           | 
           | For some reason both feel very much ideal in use. Maybe it is
           | because in each case the language syntax/ethos fits very well
           | with the choice made, and so is frictionless when developing
           | in the flow (and if used properly of course)? Maybe some
           | other reason. Hey ho.
        
         | [deleted]
        
         | larusso wrote:
         | How 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.
        
         | Conscat wrote:
         | Exceptions 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 wrote:
           | > 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.
        
         | pclmulqdq wrote:
         | There'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.
        
           | planede wrote:
           | > Exceptions have very high performance costs
           | 
           | On the sad path. On the happy path they are faster than
           | explicit error checking.
        
             | pclmulqdq wrote:
             | Kind of yes, and kind of no. On the happy path, if errors
             | are very very rare, the check is also basically free thanks
             | to branch prediction. They start to cost something when you
             | start to add a higher frequency of errors, which
             | incidentally is where exceptions cost a lot more.
        
               | mike_hearn wrote:
               | The cost is higher because of all the branches that are
               | scattered everywhere to check return codes. With
               | exceptions there's a check at the place the error is
               | thrown, but that's inevitable. There aren't checks
               | scattered throughout the rest of the code, which would
               | otherwise reduce icache utilization.
        
               | pclmulqdq wrote:
               | Arguing about icache utilization is a little silly here -
               | the code will be laid out for you as though the branches
               | are not taken (or you should force it to do so). In that
               | case, the only "waste" of icache is the CMP and JMP, an
               | additional 4-8 bytes per return, and literally 0 cycles.
               | 
               | When you do take an error, each RET takes you 1 cycle,
               | plus the 10-15 cycle mispredict for the CMP+JMP because
               | there's a stack engine in the CPU that tells you the
               | address to return to. It's counterintuitive that doing "a
               | lot" of things is cheaper than doing fewer things, but
               | it's true.
               | 
               | In comparison, an exception involves taking the one
               | control flow break to some cold control code (maybe page
               | faulting), figuring out where to go using a jump table
               | (slow), restoring the old state from that context (slow),
               | figuring out the type of the thrown object (in many
               | languages, also slow), and then handling accordingly.
               | Each of these steps can easily take 100+ cycles, and may
               | be more.
               | 
               | The math does not work out in favor of exceptions.
               | Neither do the benchmarks in most cases. You do 1 slow
               | thing to avoid doing 20 things that are trivially fast.
        
               | mike_hearn wrote:
               | The checks you're talking about are duplicated more or
               | less per statement in some types of code. Every single
               | call site ends up with an `if err != nil` or moral
               | equivalent. It can add up, also consider the extra
               | register pressure. The return values aren't valuable
               | anymore, they're just error signalling.
               | 
               | The compiler doesn't necessarily know what your error
               | types are, it can try to use heuristics to move those
               | blocks around but it's not like an exception where the
               | types are a part of the language and the compiler can
               | know that. We're talking about startup code here, nobody
               | will be annotating their error branches with manual
               | predictor probabilities, so we're limited to what the
               | compiler can do.
               | 
               | Yes the act of throwing an exception is more work but
               | it's exceptional, so doesn't matter. The slowest part is
               | calculating the stack trace anyway and that's of huge
               | value, which you don't get with error codes anyway.
        
               | pclmulqdq wrote:
               | There's no register pressure - CMP EAX, EAX // JNZ
               | $ERROR_HANDLER is the instruction sequence we're talking
               | about. Most error types are enums where 0 = "good" and
               | any nonzero value is not good. This is the inverse of the
               | "null pointer check" in C. It consumes no registers and a
               | negligible number of code bytes.
               | 
               | There is obviously a sparsity of exceptional cases where
               | error-handling code like this is worse than using
               | exceptions. I would claim that it's a lot more sparse
               | than you think. Many people use exceptions for things
               | like "file not found" or "function failed for whatever
               | reason," (my favorite) "timeout," or "bad input from the
               | user." These cases are often not that exceptional!
        
           | codethief wrote:
           | > 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 wrote:
             | They 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.
        
           | gpderetta wrote:
           | 1. Exceptions as commonly implemented in C++ have high
           | overhead in the exception path. But that's just an
           | implementation strategy. There is no reason why it wouldn't
           | be possible to generate exactly the same code as for an
           | optional type if desired (and in fact it was proposed for c++
           | cf. Herbceptions).
           | 
           | 2. So do returns, but we have long settled that SESE is
           | undesirable.
        
         | marcosdumay wrote:
         | > 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.
        
         | oconnor663 wrote:
         | I 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 wrote:
           | Zig, 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-
           | Trace...
        
         | chomp wrote:
         | It'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.")
        
         | MaulingMonkey wrote:
         | In 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 wrote:
           | See
           | 
           | https://gen5.info/q/2008/07/31/stop-catching-exceptions/
           | 
           | and
           | 
           | 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.
        
             | MaulingMonkey wrote:
             | Micro and macro are both important.
             | 
             | I've built crash collection and deduplication systems, I've
             | heard of triage that helps discount crashes generated by
             | hardware failures or overeager overclocking. I've collected
             | telemetry and setup symbol servers and source indexing to
             | streamline bug squishing, and helped build systems which
             | verify game content up-front to discover even non-code bugs
             | before they're shipped to users, and to properly attribute
             | said errors to the content that generated said errors in an
             | easily navigatable and fixable way. I've helped engineer
             | error-tollerant systems that won't require handholding by
             | engineering to recover from bugs. Plenty of focus on the
             | macro.
             | 
             | But all it takes is a single uncaught exception slipping
             | past QA to cause one to consider a recall of physical
             | product, even in this era of ubiquitous internet, for a
             | handheld console game for something as trivial as a missing
             | or corrupt sound effect. If things at the micro level are
             | neglected too much, and nothing you do at the macro level
             | can really mitigate that in a sane manner... except use
             | tools that check you're doing things right at the micro
             | level. And I have yet to see exceptions handle that micro
             | level particularly well.
        
         | duped wrote:
         | fn 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 wrote:
         | Despite 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 wrote:
           | The 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
        
         | orthecreedence wrote:
         | > 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.
        
         | jeddy3 wrote:
         | IMHO 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.
        
         | nemothekid wrote:
         | I 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.
        
           | jb1991 wrote:
           | In 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 wrote:
             | It'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/ErrorHandlingRa...
        
               | jb1991 wrote:
               | Fascinating, 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.
        
           | Jensson wrote:
           | In 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.
        
             | orthoxerox wrote:
             | Java isn't generic over exceptions. You can't write a
             | method that takes an instance of Foo and says "my method
             | throws whatever Foo.bar() throws" or even "my method throws
             | iff Foo.bar() throws".
             | 
             | And this means that your method either always demands to be
             | wrapped in a try-catch, or you migrate to unchecked
             | exceptions.
             | 
             | Rust makes errors a part of the regular type system, so
             | they automatically benefit from all its features.
        
               | mike_hearn wrote:
               | > You can't write a method that takes an instance of Foo
               | and says "my method throws whatever Foo.bar() throws" or
               | even "my method throws iff Foo.bar() throws".
               | 
               | If you could it'd mean altering the implementation would
               | automatically alter the API, which would be rather
               | unexpected.
               | 
               | That's why the Java approach is to wrap exceptions and
               | propagate causal chains. The underlying errors thrown by
               | the implementation can change but the advertised
               | exceptions don't, but no information is lost.
        
               | auno wrote:
               | > Java isn't generic over exceptions. You can't write a
               | method that takes an instance of Foo and says "my method
               | throws whatever Foo.bar() throws"
               | 
               | If you bend over far enough backwards, and squint a bit,
               | you can _kind of_ do that...                   interface
               | Runner<E extends Throwable> {           public void run()
               | throws E;         }              class Test {
               | public static <E extends Throwable, T extends Runner<E>>
               | void test(T runner) throws E {             runner.run();
               | }         }
               | 
               | It compiles. I haven't tried running it though.
        
             | jb1991 wrote:
             | > 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 wrote:
             | The 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 wrote:
               | The 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 wrote:
               | Don't know Meyer's work - any suggestions for good
               | starting points?
        
               | steveklabnik wrote:
               | Learn Eiffel. From their own explanation:
               | https://www.eiffel.org/doc/eiffel/Learning_Eiffel
               | 
               | > Remember that Eiffel, unlike other programming
               | languages, is not just a programming language. Instead,
               | it is a full life-cycle framework for software
               | development. As a consequence, learning Eiffel implies
               | learning the Eiffel Method and the Eiffel programming
               | Language. Additionally, the Eiffel development
               | environment EiffelStudio is specifically designed to
               | support the method and language. So having an
               | understanding of the method and language helps you to
               | appreciate the capabilities and behavior of EiffelStudio.
               | 
               | I read "Object-Oriented Software Construction" to do so,
               | but it was long enough ago that I googled "The Eiffel
               | Programming Language" because my brain had substituted
               | that title instead because IMHO, it's more accurate.
               | 
               | The above link should have many current resources for
               | you.
        
               | hinkley wrote:
               | There'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.
        
             | PaulHoule wrote:
             | We are in the distributed systems age. If systems are
             | composable, operations can fail for reasons that are
             | completely unfathomable to the client. It's not reasonable
             | to have a SharkBitTheOpticFiberCableException and 100,000
             | other ones that handle every reason why an operation
             | failed.
             | 
             | What the client should know is how an error affects what it
             | is doing, it wants answers to questions like
             | * Is it likely this error will recur if I retry
             | immediately? in 1 minute? in 1 day?       * What is the
             | scope of this error?  Does it affect the entire system?
             | Does it affect a particular database record?       * What
             | do I tell the user?       * What do I tell the system
             | administrator?
             | 
             | Actual improvement in this area won't come from information
             | hiding but it could come out of attaching some kind of
             | ontology to exceptions where exceptions are tagged with
             | information of the above sort, that it is not about having
             | names for them and a hierarchy, but in about having rather
             | arbitrary attributes that help the exception management
             | framework (somewhere high in the call stack!) do the best
             | it can in a bad situation.
        
               | tgbugs wrote:
               | I had a similar thought a while back [0]. Developing a
               | sane ontology of error types and their implications is a
               | hard problem, but I think it could be done. The subset of
               | errors that is the most frustrating and hard to deal with
               | are ones where, as you point out, the client will have no
               | way to estimate how long a failure mode might persist, at
               | which point you resort to exponential backoff (actually
               | probably an s-curve).
               | 
               | The issue is that sometimes the solution to the issue
               | would require the client to get up and get out a shovel,
               | and go dig somewhere or something. When the abstractions
               | break down that hard there isn't really a way for the
               | developer of the code to handle that unless they somehow
               | stuff a full blown AGI into their program, and even then
               | it would be a stretch.
               | 
               | 0. https://github.com/tgbugs/idlib/blob/master/docs/ident
               | ifiers...
        
               | adamc wrote:
               | While I think this is a good point, a lot of the answers
               | cannot be determined by the generator of the exception.
               | Your SQL library cannot know what the implications of an
               | error are -- is this a minor part of the system for which
               | the error can be logged but mostly ignored, or is it
               | critical? Etc.
               | 
               | People want error handling to vanish so that they can
               | follow the "normal" flow, but in fact error handling is
               | one of the critical things code does.
        
               | pythonaut_16 wrote:
               | This is sort of what HTTP codes get at though.
               | 
               | The server doesn't know what you want to do with a 400
               | but it knows that the problem is with the request for
               | example.
        
               | [deleted]
        
               | PaulHoule wrote:
               | Actually there is somewhat standardized set of SQL error
               | codes and they can be put into a hierarchy like the HTTP
               | codes.
               | 
               | For instance, you can have a SQL error because the syntax
               | of your SQL is wrong. If you're not doing "dynamic SQL"
               | you know this is a programming error (it doesn't matter
               | what input was supplied to the functions.) One common
               | error is "attempted to insert a row with a duplicate
               | key", frequently you want to catch that SQLException and
               | rethrow all the rest.
               | 
               | The ideal SQL library for Java would expose the hierarchy
               | implicit in SQL errors as a class hierarchy.
        
             | eternalban wrote:
             | > Note that people now consider that as a mistake
             | 
             | Correction: Some people. Java's checked and unchecked
             | exception approach is quite nice if used judiciously. It
             | certainly beats checking for error after every function
             | call (default: mostly people ignore error codes) and you
             | even get typed errors so you can trivially incorporate
             | exception handling in the conceptual design as a first
             | class design element.
             | 
             | I am frankly not sure how people get confused about
             | "control flow" and exceptions. (In decades of Java
             | programming the only thing that can still cause minor
             | reading/writing nuisance are generic types and type erasure
             | in over elaborate generic code.)
        
               | PaulHoule wrote:
               | The greatest secret of exceptions is that in most cases
               | you don't need to catch them. What should really be on
               | your fingertips is                  try {           ...
               | something ...         } finally {           ... clean up
               | ...        }
               | 
               | this (plus try-with-resources) is the genius of
               | exceptions. The tragedy of exceptions in Java is that
               | checked exceptions convert the above to
               | try {          ... something ...        }
               | catch(ACheckedExceptionThatHasNothingToDoWithThisCode x)
               | {           throw new
               | SomeOtherCheckedExceptionToPleaseTheCompiler(x)        }
               | finally {           ... do what has to be done ...
               | }
               | 
               | with the variations of                  throw new
               | AnUncheckedExceptionSoIDontVandalizeMyCodeMore(x)
               | 
               | and                  catch(...) {           // i forgot
               | to rethrow the exception but at least the compiler isn't
               | complaining        }
               | 
               | as well as                  // i forgot to add a finally
               | cause because I was writing meaningless catch clauses
               | 
               | As much as I think checked exceptions are a mistake in
               | Java, it is not hard to make up your mind about rethrows
               | and apply them in a checked or unchecked form with little
               | or no thought.
               | 
               | The unhappy path that you get for free with exceptions is
               | correct for code with ordinary control flow. Most of the
               | code has no global view of the application and is no
               | position to handle errors. On the other hand, for many
               | simple programs, the correct behavior is "abort the
               | program, clean up resources, display an error message"
               | which a sane exception system gives you _for free_
               | (except for the finally which cleans up the happy path
               | too)
               | 
               | For a complex control flow there is something high up in
               | the call stack that has global responsibility. Imagine a
               | webcrawler which is coordinating multiple threads that
               | call fetchUrl(url) fetchUrl doesn't need to catch
               | exceptions at all, just clean up with finally. What it
               | may need to do is tag exceptions with contextual
               | information that will help the coordinator make
               | decisions. That webcrawler in particular will deal with
               | intermittent failures all the time and only the
               | coordinator is in a position to decide if it wants to
               | retry and on one schedule.
        
             | newZWhoDis wrote:
             | > Note that people now consider that as a mistake, people
             | prefer having Exceptions be hidden instead of explicit and
             | requiring handling like that.
             | 
             | What people? Please tell me where they're at so I can tell
             | them they are wrong (lol)
             | 
             | But seriously, I could not disagree more.
        
               | lenkite wrote:
               | The designers of the Java functional and stream library
               | for one. None of the functional contracts have throws. So
               | you are forced to have un-checked exceptions for
               | everything, unless you want a truly mind-boggling amount
               | of try-catch everywhere which will rapidly exceed your
               | normal code by factor of 2x-3x.
        
               | mike_hearn wrote:
               | In Java, yes. Note that the JVM doesn't enforce checked
               | exceptions. It's a language level thing. So in Kotlin for
               | example, where all exceptions are unchecked, you can use
               | the streams library without needing try/catch.
        
               | PaulHoule wrote:
               | ... or you can just use a sane FP library like
               | 
               | https://github.com/paulhoule/pidove
               | 
               | Some people don't like the Lispy signatures so I did
               | start coding up a version with with a fluent interface
               | but didn't quite finish.
               | 
               | Overall I would say the implementation of lambdas and
               | method references in Java 8 was genius, but the stream
               | library was a big mistake. Part of it is that has this
               | cumbersome API that in principle would let it optimize
               | query execution by looking at the pipeline as a whole but
               | doesn't really take advantage of it.
        
           | taeric wrote:
           | I 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 wrote:
             | That 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 wrote:
               | Sorta? 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.
        
           | PaulHoule wrote:
           | Exceptions always work the same way. You learn how to read
           | code with exceptions pretty quickly.
        
             | frodowtf wrote:
             | How does an explicit raise operator like '?' work any
             | different than that? You can learn how to read it pretty
             | quickly.
        
           | wvenable wrote:
           | Assume 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.
        
             | ModernMech wrote:
             | > A function that has no possibility of error is so
             | uninteresting that focusing on that is the wrong thing.
             | 
             | I disagree, a function that has no possibility of an error
             | is a proper function, and what we need for performance
             | optimized code.
             | 
             | Proper functions by definition are just mappings from a
             | domain to a range. That mapping really shouldn't be
             | predicated on any other state, so it should never fail if
             | the inputs are valid within the domain.
             | 
             | We _need_ to focus on such functions if we want
             | performance, because we can only achieve too speeds by not
             | worrying about checking the function result for
             | correctness. Given a proper function, we should just be
             | able to compute the result and move on to the next
             | function.
             | 
             | Therefore it's of great benefit to us (as authors of
             | performant code) to separate our fallible functions from
             | our infallible ones. Keep the fallible ones iutside of hot
             | loops, only infallible ones inside, and that's a recipe for
             | mechanical sympathy of the sort that results in great
             | performance.
        
             | nemothekid wrote:
             | If 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 wrote:
               | > 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.
        
               | azov wrote:
               | _> It almost always make sense to handle an error locally
               | if you can_
               | 
               | Yes, but "if you can" does a lot of heavy lifting here.
               | In most cases you can't, and this is when Rust's ? is
               | used.
        
               | wvenable wrote:
               | > If 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?
               | 
               | No, absolutely not! You only care about errors where you
               | can retry/ignore or log and terminate so you only have
               | try/catch in those areas. So maybe one or two.
        
             | sanderjd wrote:
             | What 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.
        
             | jeroenhd wrote:
             | "Assume all things can throw" is what I've seen people do
             | in Java code that adds a million try catch wrappers around
             | everything just in case something may go wrong at some
             | point.
             | 
             | The end result is either completely unreadable or
             | impossible to figure out. "How do I return fallback data
             | for FooBarService.wiggle()" often ends up in digging
             | through (incomplete, outdated) documentation or with code
             | that breaks unexpectedly, sometimes even in production.
             | 
             | Note that Rust has the same issue, any method can panic and
             | allocation may just fail at some point. There are very few
             | ways good ways to handle those problems correctly, which is
             | why this "everything may kill your program" approach is
             | often criticised.
        
               | yetihehe wrote:
               | > There are very few ways good ways to handle those
               | problems correctly, which is why this "everything may
               | kill your program" approach is often criticised.
               | 
               | In Erlang, "everything may kill your program" is typical
               | method of operation, and there should always be some kind
               | of path to reset your state from known good values.
        
               | wvenable wrote:
               | Don't get me started on Java and checked exceptions. If
               | you don't have checked exceptions, you should not have a
               | million try/catch blocks. In fact, just the opposite.
               | Since you only care about errors when you can retry (or
               | ignore) you should only have a small number of try/catch
               | blocks. Ideally one or none.
               | 
               | My best example of this is a UI application that I built
               | that had a single try/catch block around the event loop.
               | It just displayed the error message to the user and
               | returned to the event loop. If they tried to save a file
               | to a network and failed, they got the message, and could
               | just hit save again for somewhere else. No other code
               | needed.
        
             | erik_seaberg wrote:
             | We have to be deliberate about where we retry, and how
             | quickly. It's all too easy for layers to create a death ray
             | of n factorial requests.
        
           | einpoklum wrote:
           | You 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.
        
         | jbellis wrote:
         | Error 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 wrote:
           | Ugh that's one of the worst parts of go too. Stackless errors
           | are so useless and hard to debug.
        
       | [deleted]
        
       | mamcx wrote:
       | > 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 wrote:
         | Even 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.
        
       | zeroxfe wrote:
       | If 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 wrote:
         | Not 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.
        
           | throw14082020 wrote:
           | Go is in a sweet spot where it is often used to compete with
           | both groups: [Rust, C/C++] and [Node, Python, Ruby, etc]. The
           | reason GP said it is probably because of Garbage collection.
           | 
           | I've done a bit of Rust in my job, and there are some basic
           | things that Rust doesn't have going for it:
           | 
           | - steep learning curve (this means for the first 6 months,
           | you or your colleagues are unproductive, write bad Rust which
           | your company then builds upon over time).
           | 
           | - bad error messages (even though that was a focus for the
           | rust team!)
           | 
           | - frustratingly complex for setting up test coverage
           | 
           | - Slow analyzer speed (*super laggy* on Clion, though this
           | might be a jetbrains issue)
           | 
           | - Slow compilation times (I heard somewhere that "Go just
           | goes". I've also written some Go in my free time, and
           | compilation is fast. Well IMHO, "rust will rust" - it's very
           | slow. Generics can make compilation event slower.)
           | 
           | - Verbose. I've seen a just few lines of JS get replaced with
           | hundreds and thousands of Rust.
        
             | alfalfasprout wrote:
             | Unfortunately, I'm inclined to agree.
             | 
             | Rust lives in this interesting spot where, on paper, it
             | should be superior to anything... but in practice, it's not
             | a good choice in most cases.
             | 
             | It's very easy to ramp up someone in Go that's had a
             | standard CS education and written C/C++ before. It's also
             | simple enough syntax-wise for someone who knows python well
             | enough to understand references, etc. Its stylistic
             | restrictions and not being OOP-first also mean that
             | codebases are generally readable. Compilation is also
             | extremely straight forward.
             | 
             | With Rust, I've found even very experienced C++ folks have
             | a long ramp-up period, the development toolchain is slow,
             | and the ecosystem is limited.
             | 
             | Sure, for example there are projects to enable Rust usage
             | with CUDA. But few are inclined to actually bother
             | implementing a new BLAS and GPU accelerated tensor library
             | with Rust.
             | 
             | I do think 10 years from now Rust will start getting more
             | adoption as the ecosystem and tooling improve.
             | 
             | But it's hard to argue with Go where you'll typically get
             | results that are faster or at worst comparable to Java
             | without the OOP design pattern gobbledygook, simple
             | concurrency model, and simple build process. It's "good
             | enough" for 99% of use cases.
        
               | ModernMech wrote:
               | > With Rust, I've found even very experienced C++ folks
               | have a long ramp-up period
               | 
               | I've found C++ folks _especially_ have the hardest time
               | with Rust, because they approach it using C++ idioms and
               | habits, then get frustrated when they can 't do things
               | the way they're used to.
               | 
               | I've had better success teaching Java people Rust. They
               | find it much easier to learn than C++, and I can get them
               | writing idiomatic Rust code quickly, while C++ devs are
               | still trying to get their coding habits past the borrow
               | checker.
        
               | worik wrote:
               | I think everybody has a hard time starting with Rust.
               | 
               | Even when you get confident it is still a longer process
               | writing code than C/C++. It makes you think very hard
               | about what you do carelessly in C.
               | 
               | But having spent the last few years debugging a lot of
               | Swift code, and a bit of Rust code, that time is worth it
               | I say.
               | 
               | Where Rust shines is in the debug cycle. Less of it.
               | 
               | Once you learn to surrender to the compiler, you will
               | find true bliss,....
        
               | zozbot234 wrote:
               | Go has bad interop with C/C++ and languages that use the
               | C/C++ ABI (including Rust). You can use cgo as a
               | workaround but it's clunky. So that makes an interesting
               | case for other high level, novice-friendly languages like
               | Nim, Crystal or Val/Vale/Vala.
        
             | estebank wrote:
             | > - bad error messages (even though that was a focus for
             | the rust team!)
             | 
             | I would love to hear more! (If you have the time.)
        
               | pdimitar wrote:
               | Not the fault of Rust compiler per se but in my case the
               | errors that mismatching trait impls from async libraries
               | yield can be downright suicide-inducing.
               | 
               | I recognize this is not entirely on rustc though.
        
               | steveklabnik wrote:
               | esteban of course gave you an excellent response already,
               | but just another bit of like, context here: while it may
               | not be on rustc, the developers want to go beyond the
               | norm here. rustc understands if you write async/await
               | syntax like JavaScript, and then directly proposes that
               | you switch to the Rust syntax:                   pub
               | async fn foo() -> i32 {            unimplemented();
               | }                  pub async fn bar() {             let f
               | = await foo();         }
               | 
               | gives                   error: incorrect use of `await`
               | --> src/lib.rs:6:13           |         6 |     let f =
               | await foo();           |             ^^^^^^^^^ help:
               | `await` is a postfix operation: `foo().await`
               | 
               | It isn't on rustc to understand this either, but it helps
               | a bunch of people, so the team does it anyway.
        
               | pdimitar wrote:
               | Check sibling reply. Sadly I never wrote those down. :(
               | 
               | I'll definitely do so going forward.
               | 
               | The problem is with that is the impostor syndrome: I
               | legitimately can't tell if I am an idiot and skipped some
               | basic Rust training, or the error messages are truly
               | confusing and unproductive.
               | 
               | But your messages help. I'll just write those down and
               | send them to GitHub's issue list.
        
               | steveklabnik wrote:
               | I'm not working on Rust anymore, but the previous stated
               | position on this, which as far as I know is still the
               | case, is that if it's confusing, you should file. Worst
               | case scenario is "sort we can't fix that" but it's not an
               | imposition to file issues. More is better. Because
               | exactly as Esteban said, information is valuable. Even
               | duplicates are valuable: they indicate that more than one
               | person has run into this, and therefore it's more
               | valuable than an obscure issue only one person sees.
        
               | estebank wrote:
               | Having examples of these is useful to see what we _could_
               | get rustc to do. The general case might be impossible to
               | deal with in a generic way, but we can target specific
               | patterns libraries use and emit custom errors for them.
               | The problem with these is we have to be reactive: if we
               | don 't see a problematic patter ourselves (or it isn't
               | reported to us), we can't do anything about them.
        
               | pdimitar wrote:
               | Unfortunately last I tried these code snippets was months
               | ago, was rushing like mad because it was a startup and I
               | couldn't afford to just stop and write everything down
               | and... yeah, priceless info was lost.
               | 
               | Just recently I am making a comeback to rewriting a tokio
               | 0.1 library to the latest version so I'll likely have a
               | few examples that I can post... where? In GitHub issues?
        
               | estebank wrote:
               | GitHub works great for it, for diagnostic tickets in
               | particular you can file them at https://github.com/rust-
               | lang/rust/issues/new?assignees=&labe...
               | 
               | Even if it is an "it hurts when I do this" without more
               | context it can be useful to bring the problem to our
               | attention (but the more context you provide the higher
               | the change we'll fix the problem).
        
             | dcow wrote:
             | > - Verbose. I've seen a just few lines of JS get replaced
             | with hundreds and thousands of Rust.
             | 
             | Please, more detail (=
        
               | afavour wrote:
               | JS:                   new HTMLDivElement()
               | 
               | Rust:                   struct WebBrowser {         ...
        
               | steveklabnik wrote:
               | Instantiating an object vs defining one? Yeah definition
               | would be longer.
        
               | throw14082020 wrote:
               | I should've been clearer, sorry.
               | 
               | The verbosity and complexity of
               | `wasm_bindgen`/serialization between JS and Wasm (written
               | in Rust) is primarily the thing I am frustrated at here
               | when I see hundreds and thousands of Rust code. A
               | concrete example: creating a Websocket client in
               | Javascript/Typescript vs in Rust/Wasm.
               | 
               | In general though (outside of Wasm), Rust is less
               | readable.
               | 
               | And with regards to Rust errors, I've found Rust errors
               | related to Tonic and Diesel to be quite
               | annoying/unreadable. The Diesel docs seem to blame Rust
               | for this (can't find the docs for it right now).
        
               | justinclift wrote:
               | Isn't this due to wasm having to access browser things
               | mostly _through_ browser JS interfaces?
               | 
               | eg Browsers provide JS functions that are intended for
               | JS, which are not directly exposed to Wasm. So when your
               | Wasm wants to access DOM things, access DOM functions,
               | (etc) it needs to go through a JS shim layer instead of
               | being able to call them directly.
               | 
               | If the browser dev's (or some W3C type of body?)
               | introduced those same functions, but had them be directly
               | accessible from wasm, then the JS shims wouldn't be
               | needed.
               | 
               | The JS dev's for each of the browsers though would
               | probably try and stop it ("security risk!" excuses, etc)
               | though, as that would potentially cut into "their
               | territory" and allow other languages to compete. :(
        
             | justinpombrio wrote:
             | > - Verbose. I've seen a just few lines of JS get replaced
             | with hundreds and thousands of Rust.
             | 
             | I'm curious to see those few lines of JS!
        
           | pleb_nz wrote:
           | I wouldn't group python with java and c# either. Quite
           | different beasts
        
           | ntonozzi wrote:
           | Go belongs in the exact same bucket as Java and C#.
        
             | FpUser wrote:
             | Performance wise yes. As for language features - not
             | really. Code in Go would likely have way more LOC
        
             | tptacek wrote:
             | Ergonomically, yes. Logistically, no.
        
               | mike_hearn wrote:
               | For server binaries they're typically being dropped into
               | Docker containers not scp-d to servers directly, and the
               | moment you go there you can just use jib and get a JVM
               | container easily so there's no difference in logistics.
               | 
               | For CLI tools whilst a single binary can be convenient,
               | native-image lets you get those for JVM programs too
               | these days. But it's not always the case that it's
               | enough. In practice you will often hit the need for:
               | 
               | a. Cross platform / cross builds.
               | 
               | b. A way to easily update them for your users (that isn't
               | "everyone mount this NFS/SMB drive")
               | 
               | c. Ability to ship other files e.g. third party libraries
               | written in other languages, config files, data files,
               | readmes ...
               | 
               | d. Possibly, avoiding virus scanners and Gatekeeper if
               | you have users on Windows/macOS.
               | 
               | Conveyor [1] does support distributing CLI tools (in any
               | language) that can then be updated via apt-get, the
               | Windows package manager or Sparkle on macOS. If your
               | language/runtime supports cross-building then it can do
               | it all from your developer laptop, you don't need each OS
               | to build for. The resulting artifacts are single files
               | (deb, msix/exe, zip) and it supports both self-signing
               | and regular signing if you want that.
               | 
               | It provides a few other neat features on Windows:
               | 
               | * One click install that immediately adds new tools to
               | every single terminal session without needing restarts.
               | 
               | * If you want, silent background updates Chrome-style. If
               | you don't, manually triggered updates.
               | 
               | * For JVM apps specifically it automatically configures
               | the Windows terminal to support ANSI escapes, Unicode and
               | other modern features so you can use all the same stuff
               | as on UNIX without needing to futz around with win32 or
               | wrappers.
               | 
               | Unfortunately the little default GUI that lets you
               | trigger updates and add CLI tools to your path on macOS
               | isn't officially launched yet, because it only works for
               | JVM apps and not other types of program. But if anyone
               | wants to try it just let me know, it's easy to activate.
               | 
               | If you don't need any such features then yes, a single
               | binary can be a bit more convenient than a zip. But the
               | number of situations where it breaks down is pretty high
               | and it's not so hard to handle multiple files.
               | 
               | [1] https://hydraulic.software/
        
               | tptacek wrote:
               | I want to be careful not to recapitulate every
               | conversation I've ever had with a JVM person about this.
               | I'm not claiming it's impossible to deploy JVM
               | applications; obviously, tons of people do. I'm just
               | saying people use Go and Rust because they work well in
               | situations where you want to distribute and directly run
               | a simple binary without additional tooling. That's not
               | every situation; obviously, if you can use Docker,
               | there's not much difference between a JVM app and any
               | other kind.
               | 
               | Your comment is super interesting, don't let me sound
               | like I'm trying to shoot it down. I'm being deliberately
               | terse to avoid creating receptors for language war
               | antigens to bind to.
        
               | mike_hearn wrote:
               | Sure. Given the choice of one file or 50, one file is
               | clearly better all other things being equal.
               | 
               | My feelings on this changed over time. About 10-15 years
               | ago I thought single executable output was a critical
               | feature for a language, because everywhere I went I saw
               | people saying how important it was for them, how much
               | simpler it made deployment. I figured, OK, people know
               | what they want so that's what they should get.
               | 
               | Then Docker came along. Docker images aren't single
               | files, they're the polar opposite. They aren't even
               | things you directly manipulate using the filesystem at
               | all. Yet people loved it and it took over the world.
               | Clearly what all those people demanding single-file
               | executables were actually wanting in 95% of cases was
               | simpler deployment, and they were phrasing it as single
               | executable because that was concrete and understandable
               | whereas simpler deployment is a very vague concept so who
               | knows what you'd get if you asked for it.
               | 
               | For people who are selecting Go or Rust or Graal native
               | images primarily because of single-file output, I'd
               | actually really appreciate a chance to ask a few
               | questions or interview them quickly to learn more about
               | the deployment context. Conveyor is all about deployment
               | and it's good to understand more about how people are
               | doing things and what could be better.
        
               | ntonozzi wrote:
               | Why do you say logistically no? The challenges of
               | distributing the runtime?
        
               | kcartlidge wrote:
               | There's no runtime to distribute with modern C#.
        
               | schemescape wrote:
               | Are you referring to the "compile to a big executable"
               | feature?
               | 
               | I'd love to use C# without having to deal with
               | distributing the runtime, so I'd like to hear more!
        
               | kcartlidge wrote:
               | > _I'd love to use C# without having to deal with
               | distributing the runtime, so I'd like to hear more!_
               | 
               | In the later versions of DotNet there are a couple of
               | common ways to distribute (I'd suggest either DotNet 6
               | [LTS] or preferably DotNet 7 [current]).
               | 
               | You'd usually use the _dotnet publish_ command, which
               | ideally produces one of three things, all of which are
               | self-contained and can be deployed to a clean server
               | without any framework. Ordered by worst-first (in
               | relation to your requirement):
               | 
               | 1. The halfway house from _dotnet publish_ is a folder
               | with your app /site/api alongside all the dlls needed
               | from the standard library and/or nuget. This is a
               | standalone folder, though messy.
               | 
               | 2. With an extra couple of options on the _dotnet
               | publish_ command you get it all as a single binary which
               | is exactly what you say: a big executable.
               | 
               | 3. There is another option available on the _dotnet
               | publish_ command which will use magic (probably tree-
               | shaking but I can 't remember) to produce a smaller
               | single binary by removing unused code.
               | 
               | As an aside, it's also worth noting a couple of extra
               | points:
               | 
               | * The _dotnet publish_ command can cross-compile ready-
               | to-deploy outputs for any supported platform (eg Mac or
               | Linux, using x86, AMD64, or ARM64) just by specifying the
               | combination of platform and CPU as command line options.
               | 
               | * Within C# you can mark your assets as embedded
               | resources (like an embed FS in Go) and they will also be
               | included in your output.
               | 
               | The final result varies in size depending upon what your
               | code does (and hence included libraries), and some code
               | (eg reflection) _may_ interfere with the tree-shaking (or
               | whatever) of option 3 - but it warns you whilst it
               | generates the output, and you can either ignore it or use
               | option 2.
               | 
               | Generally speaking the option 3 builds are between 1.5
               | and 2 times the size of a Go one, but you're looking
               | about 20MB to 30MB for useful stuff. Not tiny, but still
               | quite small these days. Option 2 builds probably double.
               | 
               | In use (and this is subjective) they consume a bit more
               | memory than Go, but seem more consistent/stable in that
               | usage.
               | 
               | Also note that within that 20MB-30MB build, for an api or
               | a website you get a built-in web server that can sit
               | behind nginx etc as usual, but is also good enough to
               | expose directly.
        
               | schemescape wrote:
               | Yes, "dotnet publish" is what I was thinking of. Wow, I
               | didn't realize it could cross-compile!
               | 
               | I can't quite tell from the .NET SDK repository -- any
               | idea if this stuff works on Linux (i.e. building on
               | Linux, perhaps for Windows)? I see mention of MSBuild, so
               | I'm guessing maybe not.
               | 
               | I love C#, but I abandoned it a while ago because I
               | wanted to only rely on open source tools (just to ensure
               | my code is usable in the future). Then, of course, they
               | open-sourced a bunch of stuff (including the compiler).
               | If I at least had the option to develop C# on Linux (with
               | support for cross-compiling to Windows), that would be
               | great (and honestly something I would have never expected
               | 10 years ago).
        
               | tptacek wrote:
               | Yes. It's a reason people pick Go and Rust for things.
        
             | galangalalgol wrote:
             | C# sure, but unless you are doing something pretty close to
             | the core purpose of some giant java framework java is slow
             | and verbose
        
               | tasubotadas wrote:
               | Slow and verbose compared to what?
        
               | ntonozzi wrote:
               | Java, Go and C# (and node) have very similar performance,
               | e.g. 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.
        
               | maleldil wrote:
               | It's amazing how the "Java is slow" myth survives to this
               | day.
        
               | johnny22 wrote:
               | i just read "java is slow" as "java is slow to startup"
               | and that helps.
               | 
               | Java is slow(er) to to startup, but once it's going, it's
               | pretty good.
        
               | maleldil wrote:
               | That doesn't matter if you're writing a REST api. If
               | you're writing a CLI app, then I agree that's a problem.
        
               | dboreham wrote:
               | Sometimes matters, e.g. when you deploy new code.
        
               | oauea wrote:
               | Not really, just do a rolling deployment like you should
               | be doing anyway. No one cares if the new version takes 1
               | millisecond to start up or 3 seconds because they
               | literally won't notice.
        
               | dboreham wrote:
               | Rolling deployment is a hack imho. Adds complexity and
               | hence yet more potential failure modes.
        
               | oauea wrote:
               | Hardly, it's a fantastic guardrail when combined with
               | health checks. You can say "you don't need it", but
               | everyone makes mistakes sometimes. Make those mistakes
               | not matter. You also take backups, right? Same idea.
        
               | imtringued wrote:
               | But 3 seconds isn't on the table. It is more like 20-30
               | seconds on a medium sized app and 8 seconds for a small
               | one.
        
               | bzzzt wrote:
               | If your Java app takes half a minute to initialise it's
               | the app's problem, not Java. Modern Java frameworks have
               | moved from a dynamic deployment model to statically
               | compiled and can start in milliseconds. (for example, see
               | the benchmarks on https://quarkus.io/blog/runtime-
               | performance/)
        
               | dividedbyzero wrote:
               | How would real-world JVM startup times matter in
               | deployments?
        
               | smolder wrote:
               | JVM startup times make using it in Lambda or scaling
               | container clusters awkward. Scaling can't happen fast
               | enough for traffic spikes when the startup time and cold
               | start performance is crap.
        
               | dboreham wrote:
               | You exec a process expecting it to begin operating,
               | providing some networked service, in a reasonable time.
               | Instead it doesn't do that. It spends tens of seconds,
               | sometimes minutes, running JIT and other sundry startup
               | overhead.
               | 
               | You may not have seen this if you haven't used Scala...
        
               | thefaux wrote:
               | Yeah, Scala is absurdly bad for startup time because of
               | poor modularization of the standard library. It's a
               | decent language with a terrible standard library.
        
               | dividedbyzero wrote:
               | Genuinely curious, what kind of application are you
               | running? Which JVM are you using? Are you aggressively GC
               | tuning? Very low on memory? I've used Scala from 2.8 up
               | to 3.0, for microservice systems, monoliths, data
               | pipelines, machine learning (way back), desktop apps for
               | research using Swing, an Android app (worst idea ever),
               | highly imperative to very functional, and I don't think
               | I've ever seen anything remotely as bad as that even on
               | genuinely big codebases. Hundreds of ms, sure, but
               | minutes just getting the JVM up and running? I can see
               | how that would be problematic.
        
               | imtringued wrote:
               | You reboot and suddenly your CPU is at 100% for 20
               | minutes starting every web service...
        
               | pgwhalen wrote:
               | If your CPU is at 100% for 20 minutes starting every web
               | service, that is definitely your problem, not Java's
               | problem.
        
               | galangalalgol wrote:
               | I meant slow to develop in.
        
           | marcosdumay wrote:
           | Whatever the absolute merits (or lack of them) of Go, the
           | fact is that if it's a good (enough) option for you, then
           | it's almost certain that some language will fit your problem
           | better than Rust.
        
         | Night_Thastus wrote:
         | I think it's dismissive and overly simplistic to say that Rust
         | is almost always a better option than C or C++. They're
         | different languages with different strengths.
         | 
         | One strength of C++ is that it is _far_ more established than
         | rust - and that comes with a lot of advantages:
         | 
         | * It has a larger number of people who know how to work with it
         | 
         | * It has a huge catalog of established, fully functional
         | libraries for everything you could imagine from UI to game
         | development to embedded systems to simulation to anything else
         | 
         | * It has broad support in developer toolsets in general like
         | editors and IDEs, static analysis tools, formatters, pre-commit
         | hooks, etc
         | 
         | If I'm starting a new project with C++, I can immediately know
         | that there's a huge landscape of programming already carved up
         | and ready to work with. I can't do that as easily in Rust. The
         | language, the libraries, the tools are all younger. Some of it
         | isn't as fully featured, some of it isn't nearly as stable.
         | 
         | That will improve with time, but it's a huge advantage to C++
         | right now.
        
           | Animats wrote:
           | > One strength of C++ is that it is far more established than
           | Rust - and that comes with a lot of advantages:
           | 
           | I'm painfully aware of this. Typical Rust problem, from a
           | reply I made to a posting on Reddit:
           | 
           | * WebGPU dev: WGPU updated to 0.15!
           | 
           | * Me: Might want to hold off on upgrading for a bit. See (bug
           | report on related package)
           | 
           | * WebGPU dev: Good to know. I'll keep this in mind if someone
           | has any issues when following my tutorial
           | 
           | * Me: I'm using Egui/rend3/wgpu/winit/vulkan cross platform
           | on Linux and Windows, with cross-compiling. Getting all those
           | crates to play well together is not easy. Every time
           | something in that stack changes, it's days or weeks of
           | trouble.
        
           | KMag wrote:
           | That's not the argument the GP is making. The GP is basically
           | saying that if C/C++ aren't your second choice of language,
           | then it's a sign your reasons for picking Rust are suspect.
           | 
           | They didn't say Rust is almost always better than C/C++.
           | 
           | There's perhaps the implication there, but it's certainly not
           | explicit in the GP's comments.
        
         | aisrael wrote:
         | This is really great way of putting it. Node/Python/Go were the
         | obvious alternatives for us.
        
         | autophagian wrote:
         | I feel like this is probably on the money, at least when it
         | comes to building a startup. I often use Rust where before I
         | would use Go/NodeJS/Python, but mostly because I like the type
         | system and velocity on side-projects isn't as important.
        
         | wyager wrote:
         | Precisely. If you like what you see in Rust but you don't need
         | to worry about extremely strict hardware/memory/realtime
         | constraints (i.e. you could use a memory-managed language),
         | consider Haskell instead.
        
         | galangalalgol wrote:
         | Rust is a high development cost compared to node.js python or
         | julia, but I'd say it is about the same as go or c#. Maybe a
         | little better than all of those if you consider time getting
         | test coverage. But if you are prototyping you probably aren't
         | doing that. I'd say rust is a much lower development cost than
         | c++ or java.
        
           | adastra22 wrote:
           | Golang absolutely has a faster development cycle than Rust.
           | Unless you're a Rust expert who never touches Go, but then
           | it's an issue of familiarity. Go devs hit the ground running
           | and the ergonomics are streamlined, and the borrow checker
           | and other rust restrictions don't get in the way.
        
             | galangalalgol wrote:
             | Given my downvotes you seem to be with the consensus on
             | this one. I had 30 years of c++ development going into rust
             | and I never found myself fighting the borrow checker.
             | Golang seemed the same, just started coding and stuff
             | worked mostly. But, the complexity of rust was familar
             | coming from c++ with generics and macros but without some
             | of the footguns, so it just seemed like power, not clutter.
             | 
             | I like go, but I wouldn't prototype in it, I'd pick julia
             | or python. And if I'm familiar with the problem and want to
             | code for production, rust really doesn't seem any slower to
             | develop in than go to me and perhaps a bit less verbose.
             | But in retrospect I think that is because of the direction
             | I came at rust from means my habitual coding style lined up
             | more closely with what rust expects. Its not a harder
             | coding mindset, just a different one than someone who came
             | from java would be used to.
        
               | adastra22 wrote:
               | 30 years of C++ can inoculate you to the idea of hideous
               | amounts of boilerplate, or worrying about memory
               | allocation timelines and such. I'm a 25 year C++ veteran
               | myself.
               | 
               | I recently wrote an asynchronous microservice in C++,
               | because it needed to use a C++ library I'd already
               | written. Took about two weeks of effort, and clocked in
               | at 1500 loc, not counting tests or the half-dozen
               | external dependencies. I rewrote it in 100 lines of
               | idiomatic Go using nothing except the standard library a
               | few days ago. That's a 10x reduction in both lines of
               | code and development time, although it's a bit unfair
               | because I had already done the C++ version first. That is
               | after giving up on a Rust version that was already
               | weighing in at ~1000 LOC in an unfinished state.
               | 
               | After this experience, I don't think I'd ever use C++ or
               | Rust again for a concurrent web service, unless there was
               | hard real-time latency requirements. Golang is just so
               | much better streamlined for that application, and the
               | standard library is batteries included.
        
               | galangalalgol wrote:
               | Go was designed from the ground up for that sort of
               | thing, so that makes sense. And anecdotally asymc/await
               | is a pain in rust. I've only used rust async through
               | other libraries, and not that very often. I usually use
               | plain threads.
        
               | lenkite wrote:
               | 30 years of C++ development experience means you aren't
               | going to find any PL difficult and therefore your views
               | on easy/difficult a PL is to learn and get going cannot
               | be taken seriously. :)
        
               | galangalalgol wrote:
               | While my overinflated ego enjoys your assessment, I want
               | to reiterate that the patterns that minimize friction
               | with the borrow checker aren't harder than standard
               | patterns you'd see in garbage collected OOP or Functional
               | focused languages, just different. Anecdotally here on HN
               | it seems like people who came from ocaml or f# find rust
               | even easier to adapt to than c++ people.
        
         | JamesSwift wrote:
         | That really is a great way to think about it, and my previous
         | experiences with the "wrong choice of Rust" seem so obvious
         | when filtered through this lens.
        
         | avinassh wrote:
         | Three months ago I had made exactly similar comment, it felt
         | nice to me to see the same thought echoed!
         | 
         | https://news.ycombinator.com/item?id=33845045
        
           | [deleted]
        
         | Animats wrote:
         | > 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.
         | 
         | I've been saying that for a while. If you're building web
         | backends, Rust is not a good choice. Go is so much easier. The
         | green thread system gets rid of the thread/async distinction,
         | garbage collection means you don't have to obsess over memory
         | management, and the libraries for web backend stuff are the
         | same things Google uses internally, so they're well-tested.
         | 
         | A big problem with Rust, long-term, is that the kind of
         | programs that really need it are somewhat out of today's
         | mainstream. It's not that useful for webcrap. It's not that
         | useful for phone apps. The AI people use Jupyter notebooks and
         | Python to drive code on GPUs.
         | 
         | Where do you really need Rust? Heavy-duty multi-threaded
         | programming. Operating systems. Compilers. Routers and network
         | infrastructure. Robotics, maybe. Hard real time. It ought to be
         | used more for high-performance games, but the game
         | infrastructure isn't there yet. Unreal Engine is C++ and Unity
         | is C#. Rust has Bevy and Rend3, but they're not AAA title
         | ready.
         | 
         | Perhaps Rust is fighting the last war - the mess inside C++.
        
           | pcwalton wrote:
           | > A big problem with Rust, long-term, is that the kind of
           | programs that really need it are somewhat out of today's
           | mainstream. It's not that useful for webcrap. It's not that
           | useful for phone apps. The AI people use Jupyter notebooks
           | and Python to drive code on GPUs.
           | 
           | One thing this is missing is that Rust is useful for
           | libraries callable by many different languages. You may or
           | may not want to use it to build an actual Web app (I
           | personally think it's a solid choice, but reasonable people
           | can disagree). But for building, say, the Python cryptography
           | library [1], which is used as a part of "webcrap", Jupyter
           | notebooks, and in many other domains, Rust is clearly an
           | excellent option. Nobody is going to build core Python
           | infrastructure in Go or Node, and without the plumbing
           | libraries none of the higher-level applications can function.
           | 
           | [1]: https://github.com/pyca/cryptography
        
             | huijzer wrote:
             | You mean to link against Rust binaries or can you make
             | library files too? Compared to, say, SQLite as a single C
             | file, I thought that Rust projects are not super easy to
             | use as a dependency
        
               | ameliaquining wrote:
               | Rust can output library files that use the C calling
               | convention, either static or dynamic. Doing this entirely
               | by hand is pretty annoying, because your API surface has
               | to be C-compatible (so can't contain a lot of Rust's
               | useful language features) and because you still have to
               | do the other half of the FFI to use the library from the
               | other language. However, it's possible to develop
               | automated language-specific tooling to make this easier,
               | with PyO3 being a particularly impressive example.
        
               | f_devd wrote:
               | Depends on how you link rust, using PyO3 makes it
               | arguably easier to do link python code to rust than any C
               | construction I could think off. Linking a single C file
               | into python is quite difficult (if not using JIT like
               | cppyy) because you need to make bindings & conversion
               | often on both sides for each exported function.
        
           | lumb63 wrote:
           | They are out of the mainstream, but only because "systems
           | people who have exchanged any hope of losing their virginity
           | for the exciting opportunity to think about hex numbers and
           | their relationships with the operating system, the hardware,
           | and ancient blood rituals that Bjarne Stroustrup performed at
           | Stonehenge" "SOLVE THE BEAR MENACE" [0].
           | 
           | [0]:
           | https://www.usenix.org/system/files/1311_05-08_mickens.pdf
        
           | usgroup wrote:
           | You're right. I think that it replaces C/C++ for many use
           | cases. I'm a quant, and I use it to write fast algos for
           | research. It won't be long until Rust has good high level
           | SIMD primitives like the faster crate offered. I can't see
           | myself using anything else thereafter for performant code.
           | 
           | You may be underestimating the amount of need there is for
           | performant code though. Its everywhere.
        
           | hot_gril wrote:
           | > If you're building web backends, Rust is not a good choice
           | 
           | This heuristic wouldn't work for my department because we
           | build web backends in C++. I keep telling the most senior
           | devs here that nobody does this and for good reasons
           | (velocity etc), and their response is "who cares what the
           | rest of the world does, they're just bad at C++."
        
             | Animats wrote:
             | Google developed Go specifically so they didn't have to use
             | C++ in high-volume web backends, which is what they did
             | previously.
        
           | Klonoar wrote:
           | _> I've been saying that for a while. If you're building web
           | backends, Rust is not a good choice. Go is so much easier.
           | The green thread system gets rid of the thread/async
           | distinction, garbage collection means you don't have to
           | obsess over memory management, and the libraries for web
           | backend stuff are the same things Google uses internally, so
           | they're well-tested._
           | 
           | The thing here is that _most_ web backends are basic CRUD
           | bullshit, and you fundamentally will not hit the thread
           | /async distinction, nor need to care about whether there's
           | garbage collection or not. Microsoft has used actix-web in
           | production as far as I know, it's not like the Rust web stack
           | isn't battle tested.
           | 
           |  _> Where do you really need Rust? Heavy-duty multi-threaded
           | programming. Operating systems. Compilers. Routers and
           | network infrastructure. Robotics, maybe. Hard real time._
           | 
           | These are all the things that sit adjacent to a web
           | framework, and once you step outside that CRUD happy path,
           | Rust fits very well - and in this case just "bolts on".
           | 
           |  _> It's not that useful for phone apps._
           | 
           | This is more tangential but I know of more than a few
           | companies who have written or are writing their cross-
           | platform logic in Rust instead of C++. This is really akin to
           | how some projects back Python modules with Rust: it's easy to
           | have it backing things and it beats the hell out of dealing
           | with C++.
           | 
           | And look, I'm not even saying don't use Go/Python/JS/<insert
           | your preferred language here>. You do you, your startup will
           | live or die by so many other things than choice of
           | programming language.
        
           | WJW wrote:
           | There is probably a good space for Rust in writing the
           | databases, caches and all sorts of proxies as well. I agree
           | though, for most of the stuff I need for $DAYJOB the speed is
           | nice but hardly required. It doesn't really matter if I can
           | generate a HTTP response 50 microseconds quicker if the
           | response then has to travel over the internet for 20+
           | milliseconds.
        
             | zozbot234 wrote:
             | It does matter if you're using cloud autoscaling FaaS
             | (previously known as CGI) and paying for those HTTP
             | responses by the microsecond (and by RAM usage as well,
             | which is also typically quite low in Rust).
        
               | WJW wrote:
               | Not really, the connection won't close until you are done
               | sending it all and have received the relevant TCP ACK
               | messages from the other sides. Being on autoscaling FAAS
               | or not does not matter for that.
               | 
               | In any case, if you are trying to optimize microsecond
               | usage in AWS lambda I hope you have a truly gargantuan
               | amount of traffic and/or have incredibly cheap engineers
               | or the money saved will barely match up to the cost of
               | the engineering hours sunk into them.
        
         | ozten wrote:
         | NodeJS kind of muddies the waters. It ate a lot of use cases
         | that would have previously been done in Java. That created
         | conflict between backend teams that wanted statically typed
         | code and a "boring" tech choice against "full stack" developers
         | creating a backend service.
         | 
         | I think Rust will see a lot of adoption in web services that
         | are glorified CRUD APIs. It would have been a poor choice to do
         | many of these workloads in this in C or C++ (despite the data
         | point of Amazon 1.0 LOLz).
        
           | spullara wrote:
           | The latter use case is terrible for Rust.
        
           | dirheist wrote:
           | Wouldn't you just use go/python/node for a simple crud API?
           | fastapi for python is pretty performative if you use gunicorn
           | as your runtime and time to iterate is must faster than it is
           | in rust.
        
             | mcronce wrote:
             | It depends exactly how simple that CRUD API is. If there's
             | any business logic, I'd rather get all the cheap
             | correctness guarantees that Rust provides. I don't find
             | myself making many truly dumb CRUD APIs.
             | 
             | Time to iterate is also only much faster in certain
             | situations, e.g. local development; if you have to e.g.
             | build a container image, push to a registry, and redeploy
             | to a k8s cluster somewhere, those savings become somewhere
             | between less significant and nonexistent.
        
               | nawgz wrote:
               | > Time to iterate is also only much faster in certain
               | situations, e.g. local development; if you have to e.g.
               | build a container image, push to a registry, and redeploy
               | to a k8s cluster somewhere, those savings become
               | somewhere between less significant and nonexistent.
               | 
               | Can you expand on what you mean here? I know you're not
               | implying Rust is faster to move thru a CICD pipeline, so
               | can you tell me what you do mean? I seem to be unable to
               | make a different reading
        
               | helsontaveras18 wrote:
               | "Time to iterate" is measuring how quickly you can get an
               | idea, build it in code, deploy it to your customer, and
               | get feedback.
               | 
               | If Rust is helping you make prototypes and iterate
               | quickly, I'd love to hear how you're using the language.
        
           | brimstedt wrote:
           | I've really tried to give js/ts in backend a go. Both by
           | nodejs and deno. And by kickstarting my own projects as well
           | as diving into experienced nodejs developers' code.
           | 
           | I really don't see how anyone choses nodejs/deno to anything.
           | 
           | Java imo gives you much less trouble, is more stable, has a
           | working (!!!) Unit testing setup and exceptional runtime.
           | 
           | Next on my list is to give rust a go, since I'm intrigued by
           | its features, but if I was to go fast I'd go with java any
           | day.
        
             | ye-olde-sysrq wrote:
             | "I really don't see how anyone choses nodejs/deno to
             | anything."
             | 
             | This is going to sound mean but I don't really know how to
             | phrase it more nicely. People building backends in js/ts
             | are doing so because either they, or a critical mass of the
             | people they expect to code in it, don't know any better
             | backend languages.
             | 
             | I don't mean for this to be judge-y. People have different
             | skillsets. A nodejs backend can be the right choice if
             | you're a full-stack dev or a solo dev and you mainly know
             | js and you get a lot of agility and correctness by _using
             | what you know_ instead of trying to use a  "better" choice
             | but one that _you_ yourself are less likely to use
             | correctly or quickly in your own use case.
             | 
             | It can also be the right choice if you're a big backend
             | java/etc guru but you know you want to set this thing up
             | but then just monitor/oversee frontend/fullstack devs being
             | the ones who do incremental modifications to it.
             | 
             | But yeah - without additional outside constraints and
             | everything else being equal, it doesn't make a lot of sense
             | to use nodejs as opposed to basically anything more boring
             | - be it java, rails, etc.
             | 
             | The thing that surprises me the most about node based
             | backends is that they forego both the platform maturity and
             | static-safety of java AND the ridiculous amount of
             | batteries included into django and rails, _just_ to be able
             | to use javascript, of all things. What you could rails-g in
             | a minute you could instead spend a day looking for an npm
             | package that won 't be abandoned in a month or spend
             | eternity rolling your own everything and then maintaining
             | it.
        
               | tekkk wrote:
               | Heh heh, well maybe in some cases but since TS/JS is
               | kinda the lowest common denominator in web development,
               | it's just the most convenient choice. We humans are
               | limited in our capacity to learn and take time to get
               | good at things. So it makes a lot of sense to pick a tool
               | that can be used to build the whole app with.
               | 
               | And for all of its faults, NodeJS can be fun compared to
               | something like Java which feels more like doing taxes.
               | Maybe it's the danger. Maybe it's the fact there are so
               | many packages and libraries out there - everyone can
               | contribute! Who knows, but I won't waste my time learning
               | say Rails just to use a "better" backend framework. It's
               | good enough even though I know better. There are way more
               | important things.
        
               | strokirk wrote:
               | Is there any statically typed HTML templating language,
               | for non-node languages? Genuine question.
        
               | steveklabnik wrote:
               | crates.io for Rust has 213 crates tagged "template-
               | engine" https://crates.io/categories/template-engine
               | 
               | handlebars, terra, askama, and maud are examples I
               | recognize from high up on that list.
               | 
               | Maud example: (chosen because it's the most "native Rust"
               | in a sense and is designed for HTML specifically so I
               | believe it's the closest to what you're asking for)
               | html! {           h1 { "Hello, world!" }
               | p.intro {               "This is an example of the "
               | a href="https://github.com/lambda-fairy/maud" { "Maud" }
               | " template language."           }       }
               | 
               | https://maud.lambda.xyz/
        
               | legerdemain wrote:
               | This comment is presumptuous, dismissive, and also wrong.
               | People who write application-like front ends in React
               | (etc.) want back ends that can interoperate with those
               | front ends.
               | 
               | They accomplish things like built-time code generation,
               | static server-side rendering, and other kinds of code
               | transformation that are difficult and flaky without a
               | back end that can understand JS.
               | 
               | I have looked for non-tinkertoy solutions in Java and Go.
               | There aren't any, and senior people in those communities
               | are hostile to the very idea. (Maybe remembering Java
               | Nashorn?) Maybe the only people friendly to the idea of
               | interoperable back ends are Rust people (where you have
               | libraries like Yew/Sycamore/Dioxus/Leptos that actively
               | imitate JS frameworks).
               | 
               | But yes, your claim is that the only reason to write JS
               | back ends is ignorance and enfeeblement is ignorant and
               | repugnant.
        
               | zozbot234 wrote:
               | > want back ends that can interoperate with those front
               | ends.
               | 
               | You can ingest and emit JSON in any language. You can
               | even compile backend-friendly code to run in JS on the
               | frontend, via emscripten (and increasingly, Wasm), which
               | will output very lean and JIT-friendly code. The usual
               | "isomorphic" case for backend.js is no less
               | 'presumptuous' or 'dismissive' than the comment you're
               | pointing to and criticizing here.
        
               | legerdemain wrote:
               | > You can ingest and emit JSON in any language.
               | 
               | How is this relevant? Serving a JS application to a
               | client is not like serving a JSON API.                 >
               | You can even compile backend-friendly code to run in JS
               | on the frontend, via emscripten (and increasingly, Wasm),
               | which will output very lean and JIT-friendly code.
               | 
               | Not in my experience. Compared to front-to-back JS,
               | shipping your applications as WASM ends up with downloads
               | and memory footprints that are several times larger than
               | the same application in ordinary JS, and this matters a
               | lot for slower networks and mobile clients.
               | 
               | Edit: not to mention that Go has a very limited WASM
               | story, so your "realistic" choices for shipping back end
               | code to the front end are C++ and Rust.
        
               | nawgz wrote:
               | > The usual "isomorphic" case for backend.js is no less
               | 'presumptuous' or 'dismissive' than the comment you're
               | pointing to and criticizing here
               | 
               | > You can even compile backend-friendly code to run in JS
               | on the frontend, via emscripten (and increasingly, Wasm)
               | 
               | Lol, you can't be serious
        
               | mardifoufs wrote:
               | >>increasingly, wasm
               | 
               | If you are referring to something similar to Blazor
               | (client side), yeah no imo it's pretty awful for anything
               | other than internal enterprise apps. I couldn't imagine
               | running a public facing product on that.
        
               | brimstedt wrote:
               | To clarify my point, I think nodejs is great for the
               | backend part of the view layer and to proxy requests to
               | another backend service.
               | 
               | But for business logic, database interactions,
               | calculations, etc, I really think the language construct
               | is to clumsy and does not scale nicely.
        
               | ipaddr wrote:
               | Your comments tells me you are in the group who doesn't
               | know better. Data is passed in json which is a format
               | other languages can read and send back. If that's your
               | reason for using it you do have other choices.
        
               | CuriouslyC wrote:
               | While it doesn't have the batteries, typescript's gradual
               | typing is much nicer than python's, so for some use cases
               | it's a better language.
               | 
               | All languages come with tradeoffs in terms of
               | performance, development/maintenance cost and ease of
               | hiring. Most businesses only care superficially about
               | performance, which leaves developer productivity and ease
               | of hiring. Node/typescript isn't terrible in terms of
               | developer productivity, and it's got the best hiring
               | story of any language. Python is good in both those ways
               | too, but since you already need a javascript hiring
               | pipeline for the client it's easier just to use node and
               | hire full stack devs.
        
               | worik wrote:
               | > typescript's gradual typing is much nicer than
               | python's,
               | 
               | It is not Node V. Python, but Node V Java
               | 
               | Python is a terrible choice as a backend, too.
               | 
               | It has a place as a scripting language, but so often it
               | is used to build complete systems. They suck.
        
               | helsontaveras18 wrote:
               | That's an interesting comment. I chose Node not because I
               | love it, but it's the easiest to hire for as a startup.
               | 
               | I hate configuring typescript and having to deal with
               | bundlers, package.json, esbuild, etc.
               | 
               | But Deno and Bun are just around the corner. What we need
               | is to get rid of this a la carte mentality around tooling
               | and just give everyone Typescript, batteries included,
               | and make it fast.
               | 
               | Then Node really isn't that bad anymore.
        
             | nazka wrote:
             | You should try NestJS with Prisma or Typeorm and Postgres.
             | Plus all the classic other stuff. It's a great stack.
        
             | pdntspa wrote:
             | And the IDEs which practically write your code for you. I
             | mean yeah Java is so verbose but most of that word vomit is
             | me just tabbing through autocomplete
             | 
             | I went back and prototyped a slightly similar app in Python
             | w/ a gui toolkit and I felt like I was driving through
             | exception city. I have made my career writing in dynamic
             | languages so I forgot just how pleasant it was to write in
             | a static one!
        
               | nawgz wrote:
               | > Python w/ a gui toolkit
               | 
               | Sorry, this is always the wrong choice, which is why it
               | felt so bad.
               | 
               | Writing a UI in TypeScript with any of the major frontend
               | frameworks will not require you to wade through run-time
               | exceptions
               | 
               | Java native GUI toolkits are also far more mature
               | 
               | Python and TKinter and similar stuff is always just
               | awful, I've never seen someone put together anything half
               | decent with that stack
        
             | bxparks wrote:
             | Your post is a great example why I wish Go lang was named
             | something different. Because you use the lower cased
             | versions java, rust, js, ts, nodejs, deno, etc. But all
             | your 'go' refer to the verb, not the Go language.
        
             | 8note wrote:
             | I find typescript makes the most common things I do in
             | business app software as straightforward as possible. That
             | is, making copies of objects with slightly different
             | structure to pass them to some other system. Typescript is
             | just fantastic for plumbing.
             | 
             | To do the same in java means making a billion model files
             | with a billion transformation functions on them
        
         | jjnoakes wrote:
         | I love Rust but I am still looking for the perfect blend of the
         | two camps.
         | 
         | One the one hand, Go/Node/Python/etc doesn't scratch my itch
         | for the strong type system (sum types/tagged enums mostly) and
         | on the other hand even though I like prototyping in Rust I
         | really miss things like a REPL, more terse syntax, and a bit
         | more expressiveness.
         | 
         | I think OCaml is closer to my ideal but the ecosystem isn't
         | quite there. Maybe all it needs is time.
        
           | baby wrote:
           | Yeah I would have recommended OCaml, the language seriously
           | need more developers to contribute to the ecosystem. It could
           | be much nicer.
        
           | jdlshore wrote:
           | Have you looked at Node + TypeScript? I'm just starting to
           | dig into TS, but its type system is one of the better ones
           | I've seen. And Node is nice and mature with good async
           | capabilities.
        
             | jjnoakes wrote:
             | I'd prefer something with a more sound type system, and
             | something that makes cleaning up resources easier and more
             | ergonomic.
             | 
             | This might help with cleanup:
             | https://github.com/tc39/proposal-explicit-resource-
             | managemen...
             | 
             | But I'm not sure anything will help with the type system.
             | For example, this drives me absolutely insane: https://www.
             | typescriptlang.org/play#code/MYewdgziA2CmB00QHMA...
        
           | cultofmetatron wrote:
           | its older than rust. its had plenty of time. what ocaml needs
           | is a renaissance and new blood. sadly it doesn't have the
           | momentum of being new but I agree its a compelling language.
           | I see it as a better, typed alternative to go.
        
           | tekkk wrote:
           | Pick a problem, not a tool first. Unless you're more
           | interested in the tool than the problem, then it's fine. I
           | don't love Rust, but I can get by. TS+NodeJS is okay. But I'm
           | more interested in the problems that I'm solving so I just
           | use whatever is the most suited.
        
             | jjnoakes wrote:
             | I do that today, but I believe there is still a lot of
             | opportunity for languages to approach my ideal, and I think
             | I share my ideal with others. And if a language like that
             | did exist, or could be made, I'd love to use it - changing
             | languages every project is workable, but you'd probably
             | agree (I hope?) that NOT changing languages every project
             | would be even better.
        
             | hot_gril wrote:
             | Yes. I cringe a little getting emails from startup
             | recruiters saying "join a Rust startup." As if the success
             | of their business hinges on which language they use.
             | 
             | I've found that the basic NodeJS or Python works for most
             | problems I've chosen. Not even with strong typing.
        
       | throwawaygal7 wrote:
       | Die 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.
        
       | RcouF1uZ4gsC wrote:
       | Question 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?
        
         | abledon wrote:
         | typescript
        
         | pjmlp wrote:
         | Java or .NET platforms, hardly anything else comes close in
         | languages, tooling and libraries.
        
           | JTbane wrote:
           | Agreed, those are the ecosystems that "just work".
        
         | distcs wrote:
         | Python 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.
        
         | [deleted]
        
         | secondcoming wrote:
         | Java gives you so much out of the box it's hard to ignore it.
        
         | david_allison wrote:
         | Kotlin/C# backend. React (TS) frontend
        
         | alfalfasprout wrote:
         | The 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.
        
         | steveklabnik wrote:
         | I'm not sure all things are ever equal, but I would choose
         | Rust.
        
         | orthecreedence wrote:
         | The language you're most proficient in that has a somewhat
         | decent community.
        
         | adastra22 wrote:
         | Go. Swift if it was Apple ecosystem. Rust only for very
         | specific tooling as required.
        
         | metaltyphoon wrote:
         | Java or .NET
        
         | marcosdumay wrote:
         | That's not a good question. There is no reason to pick one
         | language over another if you don't even know what software you
         | will write.
        
       | it wrote:
       | You 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 wrote:
         | Also Kotlin: `when` or `with...when` for more complex matches
        
       | jakswa wrote:
       | I 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!
        
       | frodowtf wrote:
       | The 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.
        
       | mrichman wrote:
       | So in his opinion, choosing Rust is a premature optimization?
        
         | aisrael wrote:
         | Author here - yeah, that's how I feel about it, at least for
         | startups specifically.
        
           | mrichman wrote:
           | What if your startup is in the embedded systems space, for
           | example? I don't think you'd be doing your MVP in Python.
        
             | distcs wrote:
             | Why 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 wrote:
               | (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 wrote:
             | That'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 wrote:
           | ... 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?
        
             | ReflectedImage wrote:
             | As long as you know what you are doing Ruby won't leave you
             | with more technical debt than Go or Rust.
             | 
             | How many people know how to effectively program in
             | languages like Ruby is another question altogether...
        
             | aisrael wrote:
             | To me, the language agnostic answer to reducing tech debt
             | is having a good test suite so refactoring is easier. We're
             | pretty good on that front.
             | 
             | We have definitely done large refactors before, and I'm
             | sure we'll have more in the future, but I don't think we
             | need a major rewrite or anything like that.
        
       | estebank wrote:
       | I 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.
        
         | lenkite wrote:
         | All these workarounds for easier Result handling truly make me
         | wonder whether Rust will eventually evolve exceptions as a
         | feature - of-course without _explicitly_ terming them so.
        
           | tomp wrote:
           | Rust already has exceptions, they just call them _panic_ and
           | offer exceedingly poor language support for them.
           | 
           | Some people simply live in denial, believing untruths that
           | confirm their worldview.
           | 
           | This is the same situation as with Go and generics. The
           | maintainers were in denial for a very long time, before
           | finally admitting what was obvious to some of us long before
           | [1]
           | 
           | [1] https://news.ycombinator.com/item?id=8626978
        
             | xcdzvyn wrote:
             | The implementation, outcome, use-case, and characteristics
             | of panics are all very different from exceptions. The only
             | marked similarity between the two is that they both
             | interrupt program execution (and in different ways). But I
             | feel as if you already knew that.
        
               | tomp wrote:
               | Panics support stack traces, unwind the stack, releases
               | the memory, and can either be recovered in some
               | situations, or prints an error message. Sounds like
               | Python exceptions.
        
           | steveklabnik wrote:
           | The community would revolt. Not going to happen.
           | 
           | Proposals to make the existing syntax and semantics even
           | _look_ more like exceptions were met with lots of hostility.
        
         | a5huynh wrote:
         | I've run into similar issues and found that the `thiserror`
         | crate (https://crates.io/crates/thiserror) combined w/ anyhow
         | makes a lot of that pain go away
        
           | chrisgacsal wrote:
           | I would add `snafu`(https://crates.io/crates/snafu) here as a
           | good alternative to thiserror+anyhow.
        
           | echelon wrote:
           | `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`.
        
             | anacrolix wrote:
             | here we go again!
        
           | steveklabnik wrote:
           | For 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.
        
       | Ylmaz wrote:
       | I 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."
        
         | efficax wrote:
         | in 2003 you hoofed your servers to a colocation center and
         | plugged them into the internet yourself. Deploying was
         | something you did over `scp`. Buy a big server and you're good
         | to go. That _can_ still be the case these days (see
         | stackoverflow which at least until recently was not using cloud
         | deployment). But for the most part people use cloud platforms
         | that charge by fractions of a second of cpu time. It 's never
         | been more cost effective to use a compiled language than it is
         | today. And that would also apply to bare metal bring-your-own-
         | server deployments. Want to host a monster site on just a pair
         | of beefy servers? The less resource intensive your backend, the
         | more requests you can serve per second.
        
         | dilippkumar wrote:
         | In 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
         | 
         | [1].
         | https://developers.facebook.com/blog/post/2010/02/02/hiphop-...
        
           | Ylmaz wrote:
           | The speed of your web framework is, in reality, often
           | irrelevant. Our slow nodejs app handles millions of customers
           | with a few cheap and simple caching layers. Our salaries are
           | a lot higher than the infrastructure costs.
        
           | fweimer wrote:
           | Except ... for spewing out fortune responses, most of your
           | cost by far will be in bandwidth charges. Those won't change
           | with the implementation language. If anything, the C++
           | version will just be able to burn your dollars faster.
           | 
           | (Yes, I know, it's just a silly example, but compute costs
           | are only one aspect, and the bandwidth pricing in the on-
           | brand public cloud actually tilts overall costs towards being
           | bandwidth-dominated for many applications.)
        
           | timerol wrote:
           | > 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.
           | 
           | The problem here is assuming that a 7.7x less expensive AWS
           | bill is the same value as a 7.7x more expensive development
           | time. Imagine an app that is maintained by one programmer
           | costing $10k a month and running in AWS for $1k a month. It
           | is not worth dividing that AWS cost by 10x if it means a 10%
           | development time hit. Actual numbers may vary, but
           | development often costs much more than running in AWS. (For
           | startups it's even more of a difference, because you pay AWS
           | as you get more traffic, but you pay developers before you
           | have an MVP.)
        
         | apozem wrote:
         | That'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++.
        
       | draw_down wrote:
       | The 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.
        
       | steveklabnik wrote:
       | Oxide 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 wrote:
         | Steve, I just want to say I like you a lot. :)
        
           | steveklabnik wrote:
           | Thanks, that's very kind.
        
         | ThatGeoGuy wrote:
         | Tangram 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
         | 
         | [1] https://github.com/mozilla/sccache
        
           | steveklabnik wrote:
           | Very cool!
           | 
           | And yeah while I've had similar experiences, I'm glad to hear
           | that it's so good for others. And, for example, sccache isn't
           | something I have much experience with, so repeatedly hearing
           | "it works well" is nice.
           | 
           | (Also, secret of replying to people on the internet: you are
           | often replying to the anonymous reader of the discussion as
           | much, if not more, than to the person you're replying to.)
        
         | efficax wrote:
         | I'm also at a startup using rust. It's true that the feedback
         | loop can sometimes feel bit slower. One thing that helps here
         | is being test driven so that you're not waiting for compiles
         | just so you can click through to confirm a small change in
         | behavior. But in general I think my velocity is not much slower
         | than it was at a previous company using a node backend. The
         | hardest part of software isn't typing in the code and making
         | sure it runs. It's thinking about what it should do and how it
         | should do it in the first place. And really, Rust's type system
         | is a force multiplier. We can prototype really fast, throw out
         | things and rework them with confidence because with well
         | thought out typing and tests to confirm logical behavior we
         | have strong safety guarantees. It lets you experiment and
         | investigate alternative implementations fearlessly.
        
         | faitswulff wrote:
         | Do you mind my asking what frameworks you're using in Rust on
         | the backend, if any?
        
           | steveklabnik wrote:
           | We ended up building one https://crates.io/crates/dropshot
           | 
           | Happy to talk about anything!
        
       | shmerl wrote:
       | That 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.
        
       | dhbradshaw wrote:
       | We 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 wrote:
         | Backend 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 wrote:
           | Frontend 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.
        
       | newaccount2021 wrote:
       | [dead]
        
       | alfor wrote:
       | Performance of language is almost never a big concern, but it's
       | so interesting for a technical person.
        
       ___________________________________________________________________
       (page generated 2023-02-17 23:01 UTC)