[HN Gopher] Rust: A Critical Retrospective
       ___________________________________________________________________
        
       Rust: A Critical Retrospective
        
       Author : sohkamyung
       Score  : 419 points
       Date   : 2022-05-19 10:56 UTC (12 hours ago)
        
 (HTM) web link (www.bunniestudios.com)
 (TXT) w3m dump (www.bunniestudios.com)
        
       | est31 wrote:
       | I wonder what the author means by the alloc crate not being
       | stable? The alloc crate is stable since 1.36.0:
       | https://github.com/rust-lang/rust/blob/master/RELEASES.md#ve...
       | 
       | Regarding the reproducible builds concern around paths being
       | integrated into the binary, a flag exists to get rid of paths:
       | --remap-path-prefix
       | 
       | https://doc.rust-lang.org/rustc/command-line-arguments.html#...
       | 
       | On nightly, there is also remap-cwd-prefix added by the chromium
       | team to address some of the shortcomings with remap-path-prefix:
       | https://github.com/rust-lang/rust/issues/89434
       | 
       | Overall I'm really impressed that an individual wrote 100
       | _thousand_ lines of Rust. That 's a lot!
        
         | celeritascelery wrote:
         | > I wonder what the author means by the alloc crate not being
         | stable? The alloc crate is stable since 1.36.0:
         | 
         | He is referring to the allocator api[1], not the std lib module
         | 
         | [1] https://github.com/rust-lang/rust/issues/32838
        
           | est31 wrote:
           | It doesn't seem to me that this feature is what the blog post
           | is referring to:
           | 
           | > I often ask myself "when is the point we'll get off the
           | Rust release train", and the answer I think is when they
           | finally make "alloc" no longer a nightly API. At the moment,
           | `no-std` targets have no access to the heap, unless they hop
           | on the "nightly" train, in which case you're back into the
           | Python-esque nightmare of your code routinely breaking with
           | language releases.
           | 
           | You can absolutely do your own allocator with no-std. All you
           | need for this is the alloc crate and the global_alloc
           | feature, while global_alloc was stabilized before the alloc
           | crate. Then you can call your own custom OS routines from
           | that global allocator. No need to fork std over that.
           | 
           | Now, maybe their custom use case needs something different,
           | and then it's a fair criticism, but for that I would have
           | expected a different wording of the issue, hopefully together
           | with a more detailed explanation of those use cases and how
           | the stable part of the existing alloc crate does not meet
           | them.
        
             | throwawaymaths wrote:
             | If, like OP, you're writing an operating system (or a
             | language VM) it is absolutely a thing that you will want to
             | have different allocators for different use cases, so being
             | able to set a global allocator is "not quite enough". You
             | will want certain generics (like hashes) to be able to take
             | advantage of different allocators, or even different
             | instances of allocators (say, give each thread it's own
             | arena). This is very not easy in rust, which effectively
             | requires data structures to be associated with specific
             | allocators at the type-level - which makes code sharing
             | between the "same" data structure tied to different
             | allocators quite difficult.
             | 
             | For reference, the Erlang VM, which is often joked as being
             | "an operating system unto itself" has 11? IIRC allocators.
        
               | est31 wrote:
               | The rust compiler makes use of custom arenas for
               | allocation, quite heavily in fact. And does it without
               | using the nightly-only custom allocator _alloc_ types.
               | Instead, there are functions that let you build
               | structures inside the arena, plus a bunch of macro logic
               | that builds on it. And while rustc generally uses a lot
               | of nightly features, there is nothing fundamental about
               | it that requires nightly.
               | 
               | Also, again, it's a fair concern that you want to be
               | doing custom allocators, but this is not the same as
               | claiming that no-std applications can't use the heap at
               | all, which is what the blog post did. For simple heap
               | usage, a global allocator is enough.
        
               | throwawaymaths wrote:
               | 12 allocators:
               | 
               | https://www.erlang.org/doc/man/erts_alloc.html
        
         | CryZe wrote:
         | You can write libraries against alloc on stable, but not any
         | executables, because executables not using std need to specify
         | the alloc_error_handler, which you can't do on stable yet:
         | https://github.com/rust-lang/rust/issues/51540
        
           | est31 wrote:
           | Oh I see, I stand corrected then. Thanks for pointing that
           | out!
        
         | ntoskrnl wrote:
         | Yep, this is a great article, but that section (the whole "Rust
         | Isn't Finished" section) jumped out as a place where there were
         | some simple ways he could have made his life easier. It could
         | also have been a failure of the Rust community to teach a good
         | workflow.
         | 
         | You don't need to force every contributor to upgrade every six
         | weeks in lockstep, since releases of Rust and std are backwards
         | compatible. Upgrade at your leisure, and run tests in CI with
         | the minimum version you want to support. If you're doing
         | something crazier that requires ABI compatibility between
         | separate builds (or you just want consistency), you can add a
         | `rust-toolchain` file that upgrades the compiler on dev
         | machines automatically, as seamlessly as Cargo downloads new
         | dependency versions.
        
           | burntsushi wrote:
           | To clarify a bit, the key thing here is that the OP is
           | maintaining their own patches to Rust's standard library.
           | While the API of std is itself backwards compatible, its
           | implementation uses a whole mess of unstable nightly
           | features. That means that std for Rust 1.x can't necessarily
           | be built with Rust 1.(x-1). EDIT: Nor can std for Rust
           | 1.(x-1) be necessarily built by Rust 1.x.
           | 
           | It's true that you don't have to force every contributor to
           | upgrade every six weeks, but you do very likely need to have
           | every contributor use the same version of Rust. (Which can be
           | accomplished with a rust-toolchain file, as you mention.)
           | 
           | The problem here is that if you don't do this upgrade
           | whenever a new Rust release is made, you're just putting off
           | that work to some other point. Maybe you do it every 12 weeks
           | instead of 6 weeks, that would probably be okay. But I'd
           | imagine waiting a year, for example, could be unpleasant.
        
             | ntoskrnl wrote:
             | > OP is maintaining their own patches to Rust's standard
             | library
             | 
             | Oops, that's the bit I must have missed. That does sound
             | like an ordeal and I don't have an easy answer.
        
           | albrewer wrote:
           | This is one thing I struggle with when learning Rust.
           | 
           | I want to have some examples of purely idiomatic Rust code
           | solving some bog-standard problems, that way I can copy what
           | that project's doing while I get comfortable enough with the
           | language and learn to make my own decisions.
        
       | Starlevel001 wrote:
       | > This is in part because all the Rust documentation is either
       | written in eli5 style (good luck figuring out "feature"s from
       | that example), or you're greeted with a formal syntax definition
       | (technically, everything you need to know to define a "feature"
       | is in there, but nowhere is it summarized in plain English), and
       | nothing in between.
       | 
       | I wish I wish that Rust had a better documentation system. It's
       | rather telling that any serious project has to use an entirely
       | separate static site generator because the official doc system is
       | so crippled.
       | 
       | Compare this to the Python docs, or some truly excellent Python
       | library docs (like Trio: https://trio.readthedocs.io/en/stable/,
       | or Flask: https://flask.palletsprojects.com/en/2.1.x/, or Django:
       | https://docs.djangoproject.com/en/4.0/https://docs.djangopro...),
       | which are all written using Sphinx and integrate properly with
       | crossrefs and such rather than writing manual markdown links as
       | an example.
        
         | pitaj wrote:
         | I don't find rustdoc lacking at all. It's great for API
         | documentation and it does have intradoc links.
         | 
         | Of course for a more serialized tutorial, rustdoc is not a good
         | fit so we have mdbook.
        
           | est31 wrote:
           | intradoc links are great, and I disagree with GP that rust's
           | documentation tools are bad, they are pretty great. However,
           | intra doc links have the limitation that you can't link to
           | downstream crates: https://github.com/rust-
           | lang/rust/issues/74481
        
         | veber-alex wrote:
         | You linked to docs of 3 python projects and each one looks
         | entirely different while the docs of all rust crates look
         | exactly the same.
        
           | mostlylurks wrote:
           | It is a good thing that the documentation for different
           | projects looks entirely different. I find that for me, it
           | makes it much easier to keep track of and remember everything
           | you're looking at if everything has a different aesthetic
           | anchoring it, both in working memory (if you're looking at
           | documentation for several projects simultaneously) and long-
           | term memory.
        
         | [deleted]
        
         | burntsushi wrote:
         | 'cargo doc' is absolutely one of my most favorite things about
         | Rust. I've never once seen it as crippled and I've never once
         | reached for an "entirely separate static site generator" to
         | write docs despite maintaining several serious projects.
         | 
         | Writing out explicit links sucked, but we have intradoc links
         | now. It was a huge win. But my first paragraph above was true
         | even before intradoc links too.
         | 
         | Also, I hate Sphinx. It's awesome that folks have been able to
         | use it to produce great docs, but I've never been successful in
         | using it. I disliked it enough that I wrote my own tool for
         | generating API documentation in Python.[1]
         | 
         | [1]: https://github.com/mitmproxy/pdoc
        
           | yencabulator wrote:
           | I wish cargo doc's doctests for binaries worked.
           | 
           | Internal APIs need loving too.
        
             | burntsushi wrote:
             | 'cargo doc' can produce docs for internal APIs too. On
             | mobile or I would link the docs.
        
               | yencabulator wrote:
               | https://github.com/rust-lang/rust/issues/50784
        
           | epage wrote:
           | I find rustdoc lacking for clap. rustdoc does a good job with
           | API reference documentation and is improving in its handling
           | of examples but derive reference and tutorial documentation
           | are a weak point.
           | 
           | For examples, its improving with the example scraping work
           | (e.g. https://docs.rs/clap/latest/clap/struct.ArgMatches.html
           | #meth...) but testing of example is still lacking. I've
           | written trycmd to help (https://github.com/assert-rs/trycmd).
           | 
           | For derive reference and tutorial documentation, your choices
           | are
           | 
           | - A very long, hard to navigate top-level documentation, see
           | https://docs.rs/structopt/latest/structopt/
           | 
           | - External documentation, see https://serde.rs/
           | 
           | - Dummy modules to store your documentation (I've seen this
           | used but can't remember one off the top of my head)
           | 
           | For clap, my documentation examples are best served as
           | programs and we've had a problem with these being broken. The
           | Rust CLI book has a decent strategy for this by pulling in
           | code from external files (https://rust-
           | cli.github.io/book/index.html). I was tempted to do that for
           | clap where example code and output (all verified via trycmd)
           | are pulled into an mdbook site but I've stopped short and
           | just have a README that links out to everything
           | (https://github.com/clap-
           | rs/clap/blob/master/examples/tutoria...). Its not great.
        
             | burntsushi wrote:
             | > Dummy modules to store your documentation (I've seen this
             | used but can't remember one off the top of my head)
             | 
             | Yeah I've done this and it works fantastic:
             | https://docs.rs/csv/latest/csv/tutorial/index.html
             | 
             | All the examples are tested too. So not sure about the
             | problem there.
             | 
             | Can't speak to 'derive' docs. I rarely use derives outside
             | of what std/serde give you, and I never publish any.
             | 
             | But even so, I didn't say that rustdoc has zero weaknesses.
             | :-) I said it is one of my favorite things about Rust
             | because it is just so damn good. I've tried writing docs in
             | several other languages before and they are leagues behind
             | IMO. I would absolutely not call it "crippled." Not even
             | close.
        
       | farzatv wrote:
        
       | jvanderbot wrote:
       | I loved this perspective from a hardware oriented engineer coming
       | to appreciate the enormous complexity and difficulty in providing
       | a stable and useful data structures and algorithms library as
       | part of, say, rust std.
       | 
       | Each complaint is valid, but some of it is (they admit) coming
       | from a bit of naivete. They're surprised red black trees are
       | included in the Linux kernel? why? They were surprised at how
       | useful rust std and a good? data structure foundation was? why?
        
       | alexfromapex wrote:
       | When Nightly is breaking no-std targets, is there not a way to
       | pin a specific Nightly release to prevent that?
        
         | vgel wrote:
         | There is, but then you're pinning yourself to whatever bugs are
         | in that nightly, and making the eventual upgrade that much
         | worse.
        
         | steveklabnik wrote:
         | There is, yes. You put a file in the root of your project with
         | the specific version of Rust you want, and it'll get picked up
         | and used by the tooling.
        
       | collaborative wrote:
       | I experimented with replacing an Express server with Rust while
       | keeping the same js syntax and still running on Node
       | 
       | Granted this adds overhead, but my conclusion was that the
       | performance gain is not worth the effort. Sure, memory looks
       | almost flat but response times aren't that much better
       | 
       | https://github.com/javieranton-zz/warp_like_express
        
         | lllr_finger wrote:
         | It's really cool that you experimented with this!
         | 
         | My experience is that choosing Rust just for performance gains
         | usually doesn't pay off. In your case, node already uses C/C++
         | under the hood, so some of what you're replacing could just be
         | switching that for Rust.
         | 
         | The primary reason I reach for it is when I want the stability
         | provided by the type system and runtime, and to prevent a
         | litany of problems that impact other languages. If those
         | problems aren't something I'm looking to solve, I'll usually
         | reach for a different language.
        
           | curun1r wrote:
           | > choosing Rust just for performance gains usually doesn't
           | pay off
           | 
           | Performance is a complex topic. Other languages can be fast
           | and you're likely right that with simple initial benchmarks,
           | Rust isn't going to out-perform other languages by enough to
           | make much of a difference.
           | 
           | But what about consistency of performance? Is your
           | 1,752,974,468th response going to be as fast as the ones in
           | your benchmark? To me, that's been the eye opener of
           | deploying Rust in production. We saw P100 response times
           | within 10ms of P0. The absolute worst case was below the
           | threshold for human observability from the absolute best case
           | over many months of heavy use. The metrics graphs were
           | literal flat lines for months on end across tens of billions
           | of requests. I have never seen that in any garbage-collected
           | language.
           | 
           | That kind of performance may not be necessary for your needs
           | and you may be able to tolerate or otherwise live with
           | occasional slowdowns. But there are plenty of cases where
           | consistent performance is necessary or extremely desirable.
           | And in those cases, it's nice to have Rust as an option.
        
       | dgan wrote:
       | > 100k LOC over two years
       | 
       | Dude wrote more code per week than me in last 6 month at daily
       | job
        
         | sydthrowaway wrote:
         | Well, he quit Big Tech long ago, now actually builds things
         | instead of phoning it in.
        
       | sim7c00 wrote:
       | really interesting read, and nice to see people writing operating
       | systems on rust and have also plus points besides grievances.
       | particularly enjoyed you found rust sometimes spares you the
       | 'damn i need to rewrite this entire thing' tour that C always
       | hits me with :D. now i am more hopeful my re-write-the-entire-
       | thing-in-rust was an ok'ish choice.
        
         | bunnie wrote:
         | Took me a full year of questioning life choices before it felt
         | worth it, but fearless refactoring is _so nice_. I may have
         | trouble going back to C just for that.
        
       | cek wrote:
       | As I was reading the article (in which I learned a ton about
       | Rust, of which I know little), I kept thinking "I know that
       | guy!".
       | 
       | Then I realized the OP was THE "Bunnie" of Xbox reverse
       | engineering fame [1]. <3
       | 
       | [1] https://en.wikipedia.org/wiki/Andrew_Huang_(hacker)
        
       | _wldu wrote:
       | Once rust stabilizes, I think it needs an ISO standard like C and
       | C++ have. I can't see automobile manufactures using rust without
       | one. One reason C and C++ are still widely used is due to this.
       | When we are writing code that is expected to run for decades,
       | having a corporate/community backed language is not sufficient.
       | We need global standards and versions that we can rely on decades
       | latter.
        
         | rwaksmunski wrote:
         | Lack of standards committee body making decisions is feature,
         | not a bug. Car manufactures can stick with C.
        
           | Avamander wrote:
           | Considering how "smart" cars are getting, no, they shouldn't.
        
         | pie_flavor wrote:
         | What has the standard actually gotten C and C++? Basic features
         | needed in every single code base like type punning on
         | structures are standardly UB, while design-by-committee results
         | in C++ feature hell.
         | 
         | It doesn't get any harder to write a function exhibiting a bug
         | just because there's a standard saying the function shouldn't
         | have bugs in it. No matter what, you are trusting a compiler
         | vendor that the code it compiles and the functions it links
         | against don't have bugs.
         | 
         | A standard is not a magic spell that creates better software
         | through its incantation; it provides for _multiple separate_
         | compiler vendors to be able to compile the same code the same
         | way, which is a total fiction in C /C++, and not required for
         | languages like Python or Lua. I view it as nothing more than
         | the streetlight effect.
        
           | Avamander wrote:
           | > What has the standard actually gotten C and C++?
           | 
           | As the person you replied to said, usage by other industries.
           | Replacement to MISRA C maybe even.
        
           | bregma wrote:
           | A part of the safety story of any useful toolchain compliant
           | to ISO 26262 as a SEOOC is that it verifiably implements the
           | language as documented in the standard. The "verifiably" part
           | is important. If there is no standard to verify against, how
           | do you know it's doing the right thing?
           | 
           | The language standards themselves state outright that
           | programs containing undefined behaviour are malformed. If you
           | write malformed programs, you can not assume that they are
           | safe. Don't blame language standardization for your writing
           | bad, unsafe software if you're not going to follow it.
           | 
           | In addition verifiably conformant compilers for translating
           | your programs into software, the standard allows other tools
           | to be written to perform things like static analysis,
           | complexity analysis, and conformance to other published
           | guidelines (eg. MISRA). These things are not possible where
           | the definition of the language is "whatever one single
           | toolchain vendor decides it will be this week".
        
           | KerrAvon wrote:
           | Prior to the C/C++ standardization process, every compiler
           | implemented a different dialect of those languages, and there
           | wasn't a complete and accurate specification for them. Some
           | very basic C code working with one compiler might not work on
           | another.
           | 
           | I don't think Rust or any other modern language needs to be
           | standards-org standardized, but this is a different era;
           | there is a single solid, well-documented, versioned reference
           | implementation for Rust. That was never the case for C or
           | C++.
        
             | ModernMech wrote:
             | > Some very basic C code working with one compiler might
             | not work on another.
             | 
             | I teach C and C++, and you have no idea how often I hear
             | "But it worked on my machine!" when I give back bad grades
             | due to code that segfaults when I go to run it.
        
             | ThatGeoGuy wrote:
             | Yeah I mean this is still kind of the case today, Rust just
             | avoids it because there is really only one reference
             | implementation. That may not even be true forever, Rust on
             | GCC is continuing to get more and more feature complete
             | over time. [1][2]
             | 
             | Take the "defer" keyword in GNU C - it's valid in anything
             | that has the GNU extensions but isn't standard C at all.
             | And yet, some projects swear by it (it's not a bad feature,
             | just nonstandard).
             | 
             | There's a lot of weirdness in C implementations even
             | looking across LLVM, GNU, or even when picking which libc
             | you want! Try porting any nontrivial project to work with
             | musl-libc. You might find that it's not as easy as swapping
             | in a target and building statically!
             | 
             | This is perhaps the whole rub with standardization - it's
             | bought us as developers a lot, but it doesn't cover
             | everything. The veil was kind of lifted for me when I
             | started trying to use different Scheme implementations in a
             | "standardized" way. I eventually gave up on that and just
             | use whatever implementation I am most happy with (often
             | CHICKEN, but that's a digression).
             | 
             | This gets more complicated with C++, which modern standards
             | mostly requires C11, but then also doesn't support
             | everything that C11 requires either. They're different
             | languages but yeah, compilers are gonna disagree on some of
             | the edges there.
             | 
             | [1] https://github.com/Rust-GCC/gccrs
             | 
             | [2] tangentially, Rust also avoids some UB discussion
             | because the type system is a bit more complete in terms of
             | its properties than C is, so they can resort to Option or
             | Result when things get dicey in an API. Further, there's no
             | official Rust ABI unlike C, so you don't have to worry
             | about that either...
        
           | scoutt wrote:
           | > No matter what, you are trusting a compiler vendor that the
           | code it compiles and the functions it links against don't
           | have bugs.
           | 
           | I guess the key factor about a standard is that as a
           | corporation you can point fingers if something goes wrong
           | ("the compiler and/or the MISRA C checking tools you sold me
           | are not compliant with the standard because of this bug!").
           | 
           | Also the committee can point fingers back if required ("the
           | UB is clearly specified in the standard!").
           | 
           | If I were a team manager at a big automotive factory in
           | charge of the ECU system, I would go the private way, with
           | guarantees, and paying a lot of money. In case of failures, I
           | can point fingers and someone would answer the phone on the
           | other side if I complain.
           | 
           | Who should I call or who should I point my finger at, if
           | something goes wrong because of a bug in Rust? A Github user
           | on the other side of the planet?
        
             | pie_flavor wrote:
             | If there were a standard, you'd still be pointing at
             | opposite-hemisphere github users. This is what I mean about
             | the streetlight effect - the standard has jack to do with
             | the outcome. If you are buying a product from a vendor, the
             | vendor is responsible for the product, and if you are using
             | an open-source community-managed product, it's much harder
             | to point fingers. The source of truth can be an ISO
             | standard, or it can be documentation, it doesn't matter.
        
           | shadowofneptune wrote:
           | C89 did:
           | 
           | * FILE* was a big I/O abstraction that C did not have before.
           | With Unixes and MS-DOS there were file handles, but many
           | other platforms had nothing like that.
           | 
           | * That there was a clear idea of what kind of operations were
           | well-defined was a pretty big deal. Remember, all there was
           | before was K&R to go off as a reference, or maybe you had
           | access to the Portable C Compiler. It was also a time where
           | you had a lot more oddball architectures.
           | 
           | * void return types and parameters. There was no idea of a
           | procedure in early C, only functions with useless return
           | values.
           | 
           | And of course more. There are definitely worse cases of ISO
           | standards than C and C++. Both are noticably better out of
           | it.
        
         | steveklabnik wrote:
         | The industry has already taken an interest in Rust; a lot of
         | things going on aren't public yet, but we've seen job openings,
         | and things like https://www.autosar.org/news-
         | events/details/autosar-investig...
         | 
         | ISO Standards are not generally required.
         | https://news.ycombinator.com/item?id=28366670
        
           | infamouscow wrote:
           | The US government has a very long history projecting it's
           | will on other countries. Under the guise of national
           | security, what is stopping the US government from changing
           | Rust to prevent it from working in Russia, Iran, or Canada?
           | The scenario is somewhat hyperbolic, but the US and European
           | centric nature of Rust gives people in less developed nations
           | pause.
        
             | vlang1dot0 wrote:
             | If the US gov decides to project its will on your software
             | project, an ISO standard is not going to help you at all.
             | They will sabotage the ISO process, or force your hosting
             | provider (GitHub) to remove your project or apply changes
             | to it, or just kidnap your maintainers and beat them with
             | wrenches until they comply[0].
             | 
             | If your threat model legitimately considers the US gov to
             | be a hostile actor, you need far more than a piece of paper
             | that claims what the behavior of your compiler is.
             | 
             | [0]: https://xkcd.com/538/
        
             | steveklabnik wrote:
             | How would one change a programming language to not work in
             | a country?
             | 
             | Even assuming that is possible, the answer is the same as
             | any open source project: you'd have to convince the teams
             | to make that decision. Nothing special there.
        
             | KerrAvon wrote:
             | Why would the US government care about Rust? And what could
             | they possibly legislate to change it? Do you have a
             | plausible scenario in mind?
        
               | _wldu wrote:
               | They care deeply about software security and memory flaws
               | (everyone should). If rust had an ISO standard, then it
               | could be used in more sensitive military and aerospace
               | systems.
               | 
               | https://www.stroustrup.com/JSF-AV-rules.pdf
               | 
               | Also, when something is an ISO standard, then governments
               | can't legislate that some countries may not be allowed to
               | use it.
               | 
               | https://help.duo.com/s/article/7544?language=en_US
        
               | xxpor wrote:
               | Something being an ISO standard has nothing to do with
               | being able to send OFAC after you? Fundamentally the
               | difference is providing a service vs an idea just
               | existing in the ether. You can't sanction Rust, it's just
               | an idea. You _could_ tell rustup they can 't allow
               | downloads from IPs that match sanctioned countries.
        
               | steveklabnik wrote:
               | A senator^Wcongressman asked some questions about Rust
               | and its nightly toolchain whenever Facebook's
               | cryptocurrency was under scrutiny by regulators. A French
               | government agency has a whole set of coding guidelines
               | for Rust. The government of Quatar was using Rust before
               | 1.0; haven't heard much since, but I assume they're still
               | using it. A New Zealand firefighter company was using
               | some Rust.
               | 
               | Programming languages are tools. Governments use tools.
               | It shouldn't be surprising that they may have an
               | interest.
               | 
               | That said I find your parent comment also a bit silly for
               | the other reasons you state.
        
             | unrealhoang wrote:
             | How to change an opensource programming language to prevent
             | it from working in a particular country?
             | 
             | > The scenario is somewhat hyperbolic, but the US and
             | European centric nature of Rust gives people in less
             | developed nations pause.
             | 
             | This point is correct with every semi-major programming
             | languages (top 100 popular?), so I don't think it's just a
             | Rust problem.
        
             | bogeholm wrote:
             | > what is stopping the US government from changing Rust to
             | prevent it from working in Russia, Iran, or Canada?
             | 
             | Well, for one Rust is open source, so you could download
             | the source code and comment out the country ban yourself?
        
         | avgcorrection wrote:
         | I think C caught on because it spread like a cancer through
         | institutions like universities.
         | 
         | Want to catch on? Be a virus. Not some gosh-darned
         | international standard.
        
       | wiz21c wrote:
       | FTA : "This is the point at which Rust's very strict typing and
       | borrow checker converts from a productivity liability into a
       | productivity asset."
       | 
       | that's what rust is about in my own experience. Especially with
       | threads.
        
         | epage wrote:
         | I remember someone saying that "Rust skipped leg day", feeling
         | that Rust was overly focused on the borrow checker while only
         | solving a small number of problems.
         | 
         | 1. I think its easy, especially for GC users, to forget that
         | memory management is really about resource management.
         | 
         | 2. The composability of features with the borrow checker is
         | outstanding, like proper session types / locks or Send+Sync for
         | safe use data with threads.
        
         | ModernMech wrote:
         | Me too. A lot of people who try Rust encounter a very steep
         | learning curve, and tend to question whether the borrow checker
         | and strict typing is even worth it. For me, it's allowed me to
         | build larger threaded and distributed systems than I've ever
         | been able to before. I've tried to build such systems in C/C++
         | but I've never been able to make something that isn't
         | incredibly brittle, and I've been writing in those languages
         | for 25 years. For a long time I thought maybe I'm just a bad
         | programmer.
         | 
         | Rust changed all that. I'm kind of a bad programmer I guess,
         | because Rust caught a lot of bad decisions I was making
         | architecturally, and forced me to rewrite things to conform to
         | the borrow checker.
         | 
         | This is the point at which I've found many people give up Rust.
         | They say to themselves "This is awful, I've written my program
         | one way I'm used to, and now it looks like I have to completely
         | rewrite it to make this stupid borrow checker happy. If I had
         | written in C++ I'd be done by now!" But will you really be
         | done? Because I had the same attitude and every time I went
         | back to C++ I surely built something, but if it got too large
         | it would be a sandcastle that would fall over at the slightest
         | breeze. With Rust I feel like I'm making skyscrapers that could
         | withstand an earthquake, and I actually am because the programs
         | I've written have weathered some storms that would have washed
         | my C++ code out to sea.
         | 
         | Of course one can make stable, secure, performant systems in
         | C++ and many other languages. But apparently _I_ can 't, and I
         | need something like Rust to empower me. Someone else here said
         | that Rust attracts people who want to feel powerful and smart
         | by writing complicated code, but I like to write Rust code just
         | to not feel inept!
        
       | ReactiveJelly wrote:
       | > I wrote a small tool called `crate-scraper` which downloads the
       | source package for every source specified in our Cargo.toml file,
       | and stores them locally so we can have a snapshot of the code
       | used to build a Xous release.
       | 
       | I thought `cargo vendor` already did this?
       | 
       | https://doc.rust-lang.org/cargo/commands/cargo-vendor.html
       | 
       | > This cargo subcommand will vendor all crates.io and git
       | dependencies for a project into the specified directory at
       | <path>. After this command completes the vendor directory
       | specified by <path> will contain all remote sources from
       | dependencies specified.
       | 
       | Maybe he doesn't want to depend on Cargo. Fair enough, it's a big
       | program.
        
         | bunnie wrote:
         | The big thing I wanted was the summary of all the build.rs
         | files concatenated together so I wasn't spending lots of time
         | grepping and searching for them (and possibly missing one).
         | 
         | The script isn't that complicated... it actually uses an
         | existing tool, cargo-download, to obtain the crates, and then a
         | simple Python script searches for all the build.rs files and
         | concatenation them into a builds.rs mega file.
         | 
         | The other reason to give the tool its own repo is crate-scraper
         | actually commits the crates back into git so we have a publicly
         | accessible log of all the crates used in a given release by the
         | actual build machine (in case the attack involved swapping out
         | a crate version, but only for certain build environments, as a
         | highly targeted supply chain attack is less likely to be
         | noticed right away).
         | 
         | It's more about leaving a public trail of breadcrumbs we can
         | use to do forensics to try and pinpoint an attack in
         | retrospect, and making it very public so that any attacker who
         | cares about discretion or deniability has deal with this in
         | their counter-threat model.
        
           | epage wrote:
           | Don't forget about proc macros.
           | 
           | If they don't, I wonder if one of the auditing commands
           | should support drawing attention to build.rs and proc macros
           | like this.
        
           | rcxdude wrote:
           | I often wonder about what priorities lead to the kind of
           | focus on the build system as a supply chain attack vector. It
           | seems unusual that you are in a position where you have a
           | chunk of code you want to build and have to trust the system
           | that builds it but not the code, especially in a situation
           | where such concerns can't be adequately addressed through
           | sandboxing the build system. Personally if I was concerned
           | about the supply chain I wouldn't worry about 5.6k lines of
           | rust code running during the build and more the >200k
           | (extremely conservative estimate) lines running on the actual
           | system. (not that you can ignore the build system since of
           | course it can inject code into the build, just that it's such
           | a small part of the workload of reviewing the dependencies it
           | shouldn't really be worth mentioning).
        
             | klysm wrote:
             | This also confused me a lot. I'm not sure I understand the
             | threat model...
        
       | dimgl wrote:
       | > This is a superficial complaint, but I found Rust syntax to be
       | dense, heavy, and difficult to read.
       | 
       | > Rust Is Powerful, but It Is Not Simple
       | 
       | This is exactly why I haven't gotten into Rust.
        
         | klysm wrote:
         | What do you use instead?
        
       | secondcoming wrote:
       | This was a very interesting read.
       | 
       | IMO the author underplays the visual ugliness of some Rust code.
       | Programmers tend to look at code for hours a day for years, and
       | so it should not be visually taxing to read and parse. This is
       | why syntax highlighting exists, after all.
       | 
       | But the gist I got from it is that Rust is really a very good
       | static analyser.
        
       | gary17the wrote:
       | > This is a superficial complaint, but I found Rust syntax to be
       | dense, heavy, and difficult to read
       | 
       | :)
       | 
       | If you think that Rust is dense and difficult to eyeball, please
       | do try... Swift - purely for therapeutic reasons. But not the
       | usual, trivial, educational-sample, evangelism-slideshow Swift,
       | please, but real-world, advanced Swift with generics. All the
       | unique language constructs to memorize, all the redundant
       | syntactic sugar variations to recognize, all the special-purpose
       | language features to understand, all the inconsistent keyword
       | placement variations to observe, all the inferred complex types
       | to foresee, etc. will make you suddenly want to quit being a
       | programming linguist and instead become a nature-hugging florist
       | and/or run back to Go, Python, or even friggin' LOGO. I'm tellin'
       | ya. And, when considering Swift, we're not even talking about a
       | systems programming language usable with, say, lightweight
       | wearable hardware devices, but about a frankenstein created
       | (almost) exclusively for writing GUIs on mobile devices usually
       | more powerful than desktop workstations of yesteryear :).
       | 
       | Rust is complex, but very good.
        
         | pphysch wrote:
         | Interesting, I had no idea what I was missing out on.
         | 
         | Conversation from last week:
         | 
         | Me: "So what are you working on at $company?"
         | 
         | Friend: "We're building a complete HVAC management system for
         | all types of buildings, from hardware to software"
         | 
         | Me: "Cool! What technologies are you building it on?"
         | 
         | Friend: "Swift"
         | 
         | Me: "...for like an iOS app to monitor the system?"
         | 
         | Friend: "No, everything is written in Swift. The entire backend
         | too."
         | 
         | Me: "Interesting... Have you shipped anything yet?"
         | 
         | Friend: "No but the founder is running a prototype in his house
         | and we just secured another round of funding..."
         | 
         | **
         | 
         | Is this a common thing?
        
           | gary17the wrote:
           | Considering the speed of adoption of server-side Swift as
           | well as the progress of Swift's support for Linux, I am
           | guessing we are talking about some expert variation of the
           | pump-and-dump investment technique here ;).
        
       | [deleted]
        
       | bfrog wrote:
       | Very cool, and it's true Rust is dense. On the other hand C, the
       | other typical option, either requires massive amounts of
       | ancillary tooling and macros like Zephyr to get even close to
       | doing as much at compile time. Those tools and macros add density
       | and complexity. Arguably C++ is about equivalent with fewer pros
       | over C and plenty of the cons of C still there along with some
       | new ones.
       | 
       | I appreciate the idea of trying to create a auditable OS for an
       | MMU capable CPU, the reality is once you have feature you care
       | about that becomes harder and harder it seems.
        
       | jacquesm wrote:
       | Absolute gold this article.
       | 
       | "In the long term, the philosophy behind Xous is that eventually
       | it should "get good enough", at which point we should stop
       | futzing with it."
       | 
       | I wished more people would get this.
        
         | lodovic wrote:
         | You do need a very patient sponsor for such projects though
        
           | StillBored wrote:
           | I'm not sure I understand what you mean here. If anything a
           | sponsor should be happy if there is an end goal. Far to many
           | projects feel the need to constantly futz with their product
           | long past when its "done". I think the most people understand
           | this about windows. No one is asking for yet another UI
           | change, or intrusive snooping. Windows could have been done
           | the day they released 64-bit windows XP (or windows7
           | depending on your politics), and we would have a far better
           | OS, if they had simply laid off 90% of the team leaving the
           | remaining people in a bug fix only maintenance mode.
        
       | throwaway17_17 wrote:
       | 'Before [const generic], Rust had no native ability to deal with
       | arrays bigger than 32 elements'.
       | 
       | Is this a correct statement? I have seen posts talking about
       | const generics being a new thing as of 2022. Did Rust actually
       | lack the ability to have an array with more than 32 elements? I
       | find it hard to believe that there was no way to have an array of
       | longer length and Rust still being a production level language.
        
         | jhugo wrote:
         | Since nobody else mentioned it, it's worth pointing out that
         | what e.g. JS calls an array is Vec in Rust and can be as long
         | as you want, with no ergonomic difference regardless of the
         | length.
         | 
         | Array in Rust specifically refers to an array whose length is
         | known at compile time, i.e. a bunch of values concatenated on
         | the stack, and that's what the limitations applied to.
         | 
         | The quoted statement pissed me off a bit (I otherwise enjoyed
         | the article) because it seems intended to mislead. The author
         | should have known the colloquial meaning of "array", and "no
         | ability to deal with" is factually incorrect.
        
           | dhosek wrote:
           | But see other comments--it wasn't an array limitation but
           | rather a trait limitation.
        
             | jhugo wrote:
             | Yes, I know, but the trait limitation only applies to
             | arrays, not to Vec. Many people coming from other languages
             | would reach for Vec first when they want an "array". I
             | believe that misunderstanding the meaning of "array" is why
             | GP was surprised that Rust couldn't (ergonomically) handle
             | more than 32 elements in an "array".
        
               | dhosek wrote:
               | Perhaps. But in writing an OS, sometimes you genuinely
               | _do_ want the guarantees of an array. You especially
               | would want to avoid the overhead that might come when the
               | Vec gets resized.
        
               | jhugo wrote:
               | Yes, and if you don't need dynamic size you can use an
               | array (of any size). The lack of trait implementations is
               | generally a minor inconvenience in the scale of the
               | various inconveniences of writing an OS. It doesn't stop
               | you doing anything.
        
               | bunnie wrote:
               | For the first year we did not have Vec because we were
               | no-std + stable so we literally had to use arrays and
               | could not reach out for heap allocated Vecs.
               | 
               | Things got much better after we got std and could use
               | Vec, as you note, but there are still a few locations
               | where we have no choice but to use arrays (ie some crypto
               | APIs that are too risky to redesign, the boot loader, and
               | micro kernel itself which is still no-std come to mind
               | immediately).
        
         | carry_bit wrote:
         | You could have bigger arrays, what was missing were the trait
         | implementations. Originally the traits were implemented using a
         | macro, and the macro only generated implementations for up to
         | length 32.
        
         | Animats wrote:
         | There were some awful hacks to make integer parameters to
         | generics sort of work before "const generic" went in. There
         | were tables of named values for 0..32, then useful numbers such
         | as 64, 128, 256, etc. Those haven't all been cleaned out yet.
        
         | masklinn wrote:
         | It's not quite correct no.
         | 
         | Before const generics most traits were only implemented up to
         | 32 elements though, which could be quite annoying. Even more so
         | as the compilation error was not exactly informative.
        
         | est31 wrote:
         | You have always been allowed to have arrays longer than 32
         | elements, but _dealing_ with them used to be hard. Beyond the
         | Copy trait, which is a compiler builtin, many traits weren 't
         | implemented for arrays with more than 32 elements.
         | 
         | The first such change was implemented in 1.47.0 in 2020 where a
         | bunch of traits were made work on all array sizes:
         | https://github.com/rust-lang/rust/blob/master/RELEASES.md#ve...
         | 
         | It took a few releases, until 1.51.0 in 2021, until custom
         | traits could be implemented for arrays of any length:
         | https://github.com/rust-lang/rust/blob/master/RELEASES.md#ve...
         | 
         | And the feature is still limited. For example, legacy users
         | like serde still can't switch to the new const generics based
         | approach, because of the same issue that the Default trait is
         | facing. Both traits could be using const generics, if they were
         | allowed to break their API, but neither want to, so they are
         | waiting for improvements that allow them to switch without
         | doing a hard API break.
        
       | daviddever23box wrote:
       | Nicely balanced article.
        
       | alkonaut wrote:
       | > "Hi, run this shell script from a random server on your
       | machine."
       | 
       | You shouldn't run scripts from a random server but you probably
       | have to consider running scripts from a server you trust. If you
       | don't trust the server you run the script from, are you really
       | going to run the executables this script installs? If we ignore
       | the idea of downloading and building every program from source,
       | then you'll download and run programs compiled by someone else.
       | And you need to trust them, or sandbox the programs. There are no
       | alternatives.
       | 
       | Yes, the bash script or msi can kill your dog and eat your
       | homework but there isn't much we can do about that without
       | running things in in sandboxes - and the (old/normal) windows app
       | model doesn't have that.
       | 
       | Auditing the script won't help you, because it'll say it will
       | install a program somewhere. Which is what you want, so you'll
       | consider the audit "ok". But the people who wrote the
       | script/installer are the same people that created the program (or
       | have compromised the computers producing both) and now you'll run
       | the rustc.exe program you just installed and _that_ will eat your
       | homework!
       | 
       | To most people there is no difference in how transparent a bash
       | script is compared to an msi. Downloading an msi from a https
       | server I trust, signed with a cert I trust, is something I'm
       | mostly comfortable with. The same applies to running a bash
       | script from a location that is trustworthy.
        
         | samatman wrote:
         | This is threat modeling. Bunnie Huang's threat model for
         | Precusor is considerably more stringent than the ordinary, to
         | put it mildly.
         | 
         | Compare this to a C program where love it and hate, it's just a
         | bunch of files that get included by concatenation. There's no
         | magic to make your life easier or get you in trouble,
         | everything is done via manual transmission.
         | 
         | The article goes into why they haven't been able to apply this
         | approach to Rust, even though they would like to.
        
         | usrn wrote:
         | With the other languages the apps on my machine are built with
         | (C, and to a large degree Python) I have the benefit of the
         | distribution maintainers at least looking in the general
         | direction of the source for things I install (including
         | development libraries.) Tools like Cargo shortcut that and open
         | me up to a lot of nastiness. It's very similar to the problem
         | on Windows really and I wouldn't be surprised if you started
         | seeing malware disturbed that way like we're currently seeing
         | on NPM and Pypi.
        
           | pornel wrote:
           | rustup in particular is well-behaved. It installs itself in a
           | single directory, without modifying the system, apart from
           | PATH which it warns you about, lets you skip it, and when it
           | does it, it does with care.
           | 
           | OTOH many distros don't take care to build and package Rust
           | properly. For example, Rust patches its version of LLVM to
           | avoid known bugs. The particular combination of Rust version
           | + LLVM version is most tested. Distros that insist on
           | unbundling build Rust with a stock LLVM that doesn't have
           | these bugfixes, and often is an older version of LLVM that
           | hasn't been thoroughly tested with Rust.
           | 
           | Then there's the mismatch of upgrade approach between the
           | Rust project and most distros. Rust uses an "evergreen"
           | (Chrome-like) approach to upgrades, in which the focus is on
           | making upgrades seamless and not breaking anything so that
           | they can be small and frequent. Most distros prefer
           | infrequent big upgrades, so they package unusably old and
           | officially unmaintained versions of Rust for no good reason.
        
         | kbenson wrote:
         | To me, the problem has never been that you're running a shell
         | script from some remote source, but that you're expected to
         | pipe it directly into an interpreter so the existence of what
         | you actually ran is ephemeral.
         | 
         | There are the various levels of trust that you need to account
         | for, but as you and others bite, that isn't specifically
         | different to most people than some installer.
         | 
         | What _is_ different is that there 's no record of what you ran
         | if you pipe it to an interpreter. If, later, you want to
         | compare the current script available against what you ran,
         | there's no easy way.
        
           | xigoi wrote:
           | Nothing prevents you from doing                   curl >
           | install.sh         less install.sh         sh install.sh
        
             | kbenson wrote:
             | Yes, that's the point. You can, and probably should do
             | that, but the guides don't bother with what is essentially
             | making one command two because two commands is one more for
             | someone to screw up.
             | 
             | I think the trade off they are taking is fundamentally a
             | bad one with respect to security and accountability. It's
             | not even about checking the script ahead of time. It's
             | about checking what was actually run at a later date to see
             | what happened. If the script is never stored to disk,
             | determining whether a short lived hack of the script source
             | affected you is much harder.
        
         | Datenstrom wrote:
         | It always comes back to trusting trust [1].
         | 
         | [1]:
         | https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_Ref...
        
           | Quekid5 wrote:
           | And the response to that: https://dwheeler.com/trusting-
           | trust/
        
         | amalcon wrote:
         | Auditing the script can certainly help, just not against
         | malice. E.g. if the script is not set up in such a way that it
         | protects against partial execution, then this represents a kind
         | of vulnerability (truncation) that signed MSI/.deb/etc files
         | simply do not, by the design of the file format.
         | 
         | Yes, it's possible (even easy) to write a curlbash script that
         | doesn't have this issue (or the various other issues).
         | Reviewing the script still buys you _something_.
        
         | [deleted]
        
         | Confiks wrote:
         | > Auditing the script won't help you, because it'll say it will
         | install a program somewhere. Which is what you want, so you'll
         | consider the audit "ok" [but that program is made by the same
         | people as the installation script].
         | 
         | Your argument doesn't take into consideration that build
         | artifacts / software releases have culture and best practices
         | behind them. Such releases are often considered, tested, cut,
         | digested, signed and included in package managers delegating
         | trust.
         | 
         | Many one-off installation shell scripts are not afforded that
         | culture, especially when maintained from within (static)
         | websites that update frequently. On the other hand, they are
         | small enough for you to audit a bit. If you'd compare the
         | script with one that someone else downloaded a month earlier
         | (i.e. archive.org), that would help a lot to establish trust.
         | 
         | > If we ignore the idea of downloading and building every
         | program from source
         | 
         | Your argument is equally valid when building every program from
         | source. You will not be able to review the source code of
         | moderately large programs. You will need to delegate your trust
         | in that case as well.
        
       | beardicus wrote:
       | bunnie is so kind and thoughtful, even when being critical.
       | compare this to the typical frothy-mouthed 'rant' format we see
       | here.
       | 
       | i'm sure rants are cathartic for the writer, but i rarely find
       | them compelling.
        
         | jacquesm wrote:
         | Not only that, he's modest.
        
         | rob74 wrote:
         | Well, that's the difference between the "I like [X], but have a
         | few complaints that I want to get off my chest" kind of rant
         | and the "I hate [X], and want to convince everyone how bad it
         | is and to never ever use it again" kind of rant...
        
       | StillBored wrote:
       | " Yes, it is my fault for not being smart enough to parse the
       | language's syntax, but also, I do have other things to do with my
       | life, like build hardware."
       | 
       | and "Rust Is Powerful, but It Is Not Simple"
       | 
       | among all the other points, should be enough to disqualify it for
       | mainstream use. The core of most arguments against C++ boil down
       | to those two points too. If a large percentage of the engineers
       | working in the language have a problem understanding it, they are
       | going to have a hard time proving that their aren't any
       | unexpected side effects. Of which both C++ and rust seems to be
       | full of, given the recent bug reports in rust and projects people
       | are using it in.
       | 
       | So, I'm still firmly in the camp that while there are better
       | system programming languages than C, rust isn't one of them (hell
       | even Pascal is probably better, at least it has length checked
       | strings).
        
         | IshKebab wrote:
         | > The core of most arguments against C++ boil down to those two
         | points too. If a large percentage of the engineers working in
         | the language have a problem understanding it, they are going to
         | have a hard time proving that their aren't any unexpected side
         | effects.
         | 
         | That's true for C++ but not for Rust, because Rust will _tell_
         | you if there 's some kind of unexpected behaviour that you
         | didn't think about, whereas C++ will allow UB or whatever
         | without telling you.
         | 
         | That's the big difference between (safe) Rust's complexity and
         | C++'s complexity. They are both very complex, but in Rust it
         | doesn't matter _too_ much if you don 't memorise the complexity
         | (complicated lifetime rules, etc.) because it will just result
         | in a compile error. Whereas in C++ you have to remember the
         | rule of 3... no 5... etc. (that's a really simple example;
         | don't think "I know the rule of 5; C++ is easy!").
        
         | klysm wrote:
         | > among all the other points, should be enough to disqualify it
         | for mainstream use. The core of most arguments against C++ boil
         | down to those two points too.
         | 
         | Nope not at all, that's not a valid comparison.
         | 
         | I argue that there is no simple solution that affords what rust
         | does. Engineers have to use their heads to write correct and
         | fast software. I'm so tired of people just accepting lack of
         | memory safety because it's "hard" to do correctly. There are
         | real consequences to the amount of insecure trash that exists
         | because of this mindset.
        
         | masklinn wrote:
         | > The core of most arguments against C++ boil down to those two
         | points too.
         | 
         | No, the core arguments against C++ boil down to it not
         | providing enough value for these costs, and that its
         | complexities are not orthogonal and interact sub-optimally with
         | one another so the complexities compound superlinearly.
        
           | StillBored wrote:
           | Which completely misses how people use C++ as a systems
           | programming language. For the most part those users treat it
           | like a better C, only reaching for C++ features when its an
           | overwhelming advantage over C and generally banning
           | significant parts of the language.
           | 
           | See arudino for one example.
        
             | avgcorrection wrote:
             | You've painted yourself in a corner considering your
             | argument against Rust was its complexity.
        
           | Animats wrote:
           | The basic problem with C++ is that it has hiding without
           | memory safety.
           | 
           | C has neither hiding nor memory safety. Most newer languages
           | have both. C++ stands alone as a widely used language with
           | high level unsafe abstractions. This is the source of most
           | buffer overflow security advisories.
        
         | sophacles wrote:
         | In that case we need to disqualify: Linux, threading,
         | networking, anything graphical, anything involving a database,
         | anything that has the ability to write memory that is read by
         | other lines of code, and probably any computer that allows
         | input and/or output just to be safe.
        
           | StillBored wrote:
           | I guess my point isn't really clear. Its more a case, of your
           | just swapping one set of problems for another. People
           | shouldn't avoid hard problems, but they should be seeking to
           | solve them with better tools, not ones that just translate
           | the problem domain without providing a clear advantage.
           | 
           | In the grand scheme your looking for the optimal intersection
           | of simple/expressive/performant/safe and rust seems to fail
           | on the simple/expressive axis vs just simple C which people
           | chose over languages like C++ which are more expressive
           | because that expressiveness is a source of bugs. And on the
           | safety side, rust fails miserably when compared with more
           | fully managed environments. So, it becomes a question of
           | whether that additional cost provides much vs just spending
           | more putting guardrails around C/C++/etc with more formal
           | methods/verifiers.
        
             | athrowaway3z wrote:
             | > And on the safety side, rust fails miserably when
             | compared with more fully managed environments.
             | 
             | That's a rather extreme, unsubstantiated, and imo false,
             | claim to just throw out there as a matter of fact.
             | 
             | And I'd also be curious how you can square putting enough
             | formal methods/verifiers around C/C++ without creating a
             | far worse entry into the simple/expressive axis than rust.
        
             | avgcorrection wrote:
             | > a question of whether that additional cost provides much
             | vs just spending more putting guardrails around C/C++/etc
             | with more formal methods/verifiers.
             | 
             | So the conclusion (or the closest you get to proposing an
             | alternative strategy) is to just to pour more tens of
             | millions down the black hole called Cartographing The Wild
             | West of Pointers. Hardly pragmatic.
        
         | lawn wrote:
         | C++ is one of the most used languages, and it does seem to me
         | that Rust has enough momentum going for it to be a commonly
         | used system programming language as well.
         | 
         | I do agree with his points, but I don't think it's enough to
         | disqualify it for mainstream use.
        
       | nu11ptr wrote:
       | > This is a superficial complaint, but I found Rust syntax to be
       | dense, heavy, and difficult to read
       | 
       | I'm a huge Rust fan, but sort of agree. First, I dislike C-style
       | syntax in general and find it all very noisy with lots of
       | unnecessary symbols. Second, while I love traits, when you have a
       | trait heavy type all those impl blocks start adding up giving you
       | lots of boilerplate and often not much substance (esp. with all
       | the where clauses on each block). Add in generics and it is often
       | hard to see what is trying to be achieved.
       | 
       | That said, I've mostly reached the conclusion that much of this
       | is unavoidable. Systems languages need to have lots of detail you
       | just don't need in higher level languages like Haskell or Python,
       | and trait impls on arbitrary types after the fact is very
       | powerful and not something I would want to give up. I've even
       | done some prototyping of what alternative syntaxes might look
       | like and they aren't much improvement. There is just a lot of
       | data that is needed by the compiler.
       | 
       | In summary, Rust syntax is noisy and excessive, but I'm not
       | convinced much could have been done about it.
        
         | SemanticStrengh wrote:
         | What kind of meaningful data is passed (besides lifetimes) that
         | isn't passed in Kotlin or scala 3 extension methods?
        
           | masklinn wrote:
           | Ah yes, "what kind of meaningful data is passed besides the
           | most important concept in the language?"
           | 
           | Also, the ownership mode, a concept entirely missing from
           | Kotlin or Scala.
           | 
           | As GP says, Rust's syntax is pretty noisy, but much of the
           | noise is answers to questions _other languages don 't even
           | ask_.
           | 
           | And many complains are requests for additional noise for
           | things which are just regular in Rust, like additional
           | syntactic sugar for Option and Result.
        
         | Animats wrote:
         | The main Rust syntax is OK, but as the author points out,
         | macros are a mess.
         | 
         | The "cfg" directive is closer to the syntax used in ".toml"
         | files than to Rust itself, because some of the same
         | configuration info appears in both places. The author is doing
         | something with non-portable cross platform code, and apparently
         | needs more configuration dependencies than most.
        
         | logicchains wrote:
         | >That said, I've mostly reached the conclusion that much of
         | this is unavoidable. Systems languages need to have lots of
         | detail you just don't need in higher level languages like
         | Haskell or Python, and trait impls on arbitrary types after the
         | fact is very powerful and not something I would want to give
         | up.
         | 
         | Have you checked out C++20 concepts? It supports aliases and
         | doesn't require explicit trait instantiations, making it
         | possible to right such generic code with much less boilerplate.
        
           | loeg wrote:
           | My experience in C++ prior to 20 is that it is a lot more
           | verbose/boilerplatey than Rust. I'd love to see that get
           | better, but I think C++ is starting from significantly
           | behind.
        
             | jcelerier wrote:
             | C++17:                   template<typename T,
             | std::enable_if_t<std::is_floating_point_v<T>, int>* =
             | nullptr>         void func(T fp) { ... }
             | 
             | C++20:                   void func(std::floating_point auto
             | fp) { ... }
        
               | Frizi wrote:
               | There is an equivalent syntax in Rust to both of those
               | examples, and in both cases I find it less verbose. The
               | template variant is roughly equivalent to:
               | fn func<T: FloatingPoint>(fp: T) { ... }
               | 
               | And the "auto" variant is similar to impl argument in
               | Rust:                   fn func(fp: impl FloatingPoint) {
               | ... }
        
               | jcelerier wrote:
               | I really don't see in which way the second case is less
               | verbose especially if you add a non-void return type,
               | e.g. i32. The first case would also be doable like this,
               | which is pretty munch the exact same than your first
               | example with the added "template" keyword
               | template<std::floating_point T>          void func(T t) {
               | ... }
               | 
               | (also, it's not really equivalent - if I'm not mistaken
               | with traits you can only use what the trait declares ; in
               | C++ you can for instance do something like
               | template<typename T>         concept CanBlah = requires
               | (T t) {            t.blah();         };
               | 
               | and still be able to do                   void
               | func(CanBlah auto t) {            log << "func:" << t;
               | t.blah();         }
               | 
               | instead of polluting the prototype with all possible side
               | concerns)
        
         | ducktective wrote:
         | > I found Rust syntax to be dense, heavy, and difficult to read
         | 
         | Reminds me of this section of Rich Hickey talk:
         | https://www.youtube.com/watch?v=aSEQfqNYNAc
        
           | voorwerpjes wrote:
           | There are similar issues in Rust to the one Hickey talks
           | about in Java, in terms of cognitive overload and difficulty
           | in a human parsing the program. However, I've found rust
           | largely avoids issues with a bunch of different classes and
           | with their own specific interfaces with a bunch of getters
           | and setters in the HTTP servlet example because of Trait
           | interface reuse.
        
         | fulafel wrote:
         | From the modern systems programming languages set, Go does
         | better in this respect. But admittedly it doesn't reach to
         | quite as low in fitness for low level programming as Rust.
        
           | weatherlight wrote:
           | Go is a systems programming language?
        
             | pjmlp wrote:
             | Depends if one considers compilers, linkers, networking
             | stacks, kernel emulation, unikernels, userspace drivers,
             | databases, GPGPU debugging systems programming or not.
             | 
             | Despite my opinion on Go's design, I rather would like to
             | see people using Go instead of C for such use cases.
        
             | tptacek wrote:
             | Yes. The only people for whom this is controversial are
             | message board nerds. The actual language designers don't
             | have much trouble over the concept. Here's a link to the
             | designers of Rust, C++, Go, and D on a panel having little
             | problem working through the nuances:
             | 
             | https://news.ycombinator.com/item?id=31227986
             | 
             | This perpetual debate reminds me of the trouble HN used to
             | have with the concepts of "contractors" and "consultants",
             | where any time someone mentioned that they were doing
             | consulting work there'd be an argument about whether it was
             | in fact contracting. It's a message board tic, is what I'm
             | saying, not a real semantic concern.
        
               | monocasa wrote:
               | To be fair, that first question about 'what is a systems
               | programming language' is answered by Rob Pike then Andrei
               | Alexandrescu as
               | 
               | Pike: When we first announced Go we called it a systems
               | programming language, and I slightly regret that because
               | a lot of people assumed that meant it was an operating
               | systems writing language. And what we should have called
               | it was a 'server writing language', which is what we
               | really thought of it as. As I said in the talk before and
               | the questions, it's turned out to be more generally
               | useful than that. But know what I understand is that what
               | we have is a cloud infrastructure language because what
               | we used to call servers are now called cloud
               | infrastructure. And so another definition of systems
               | programming is stuff that runs in the cloud.
               | 
               | Alexandrescu: I'm really glad I let Rob speak right now
               | because my first question was 'go introduces itself as a
               | systems programming language' and then that disappeared
               | from the website. What's the deal with that? So he was
               | way ahead of me by preempting that possible question.
               | 
               | So it seems to me that they struggle with the nuances of
               | the concept as much as the commenters here, particularly
               | as it pertains to Golang.
        
             | fulafel wrote:
             | Yes, as it's used for that a lot. Eg many databases
             | (CockroachDB, Prometheus, InfluxDB, dgraph etc), gVisor,
             | Kubernetes, Fuchsia, etcd, and so on. And also in the
             | origin story it was aiming to compete with C++ for many use
             | cases IIRC.
        
             | mindcrime wrote:
             | That's tricky to answer, because it depends a lot on what
             | you count as "system software". If you mean literally "the
             | operating system", then arguably not. But if you include
             | middleware, databases and other "infrastructure" stuff,
             | then arguably yes.
        
               | johndoe0815 wrote:
               | Go has been used to implement OS kernel code, e.g. in the
               | Biscuit OS from MIT: https://github.com/mit-pdos/biscuit
               | 
               | Of course, the garbage collector did not exactly make it
               | easier - but it's an interesting piece of software.
        
               | mindcrime wrote:
               | _Go has been used to implement OS kernel code,_
               | 
               |  _but it 's an interesting piece of software._
               | 
               | Agreed. And I didn't mean to imply that it's _impossible_
               | to use Go that way, but I think it 's fair to say that
               | it's less common and perhaps even less desirable to do
               | that.
               | 
               | OTOH, people have written (at least parts of) Operating
               | Systems in Java[1] even, so never say never...
               | 
               | [1]: https://github.com/jnode/jnode
        
               | jandrewrogers wrote:
               | A proper database can be implemented in python -- I've
               | done it -- but that doesn't make it a systems language. A
               | "systems language" comes with the strong implication that
               | it is possible to write an implementation of most
               | software that is competitive with the state-of-the-art in
               | terms of performance, efficiency, and/or scalability.
               | That is only possible in languages like C, C++, Rust, and
               | similar, hence the "systems language" tag.
               | 
               | Languages that are not systems language trade-off this
               | capability for other benefits like concise expressiveness
               | and ease of use.
        
             | UnpossibleJim wrote:
             | It _can_ be, but I wouldn 't recommend it personally:
             | 
             | https://golangdocs.com/system-programming-in-go-1
             | 
             | EDIT: formatting
        
           | veber-alex wrote:
           | Go is not a systems programming language.
           | 
           | I also personally find Go syntax to be horrible, especially
           | now with generics.
        
             | pjmlp wrote:
             | Depends if one considers compilers, linkers, networking
             | stacks, kernel emulation, unikernels, userspace drivers,
             | databases, GPGPU debugging systems programming or not.
             | 
             | I personally consider better use Go than C for such
             | purposes, even if they aren't "systems programming".
        
             | Thaxll wrote:
             | The Go syntax is fine and easy to read, you don't need to
             | know Go to undertsand what the code is doing, can't say the
             | same for Rust.
        
               | ohCh6zos wrote:
               | I think this is a matter of opinion not fact. I have
               | worked as a Go programmer for three separate companies
               | and it may be the least readable, least understandable
               | language I have encountered.
        
               | Thaxll wrote:
               | Well it's hard to argue against a language with 25
               | keywords.
        
           | jerf wrote:
           | Oh, not even close. It does what most languages do and just
           | elides, ignores, or hard-codes the answers to all the
           | questions Rust has. That's _a_ solution, sure, a very valid
           | one chosen by many languages over many decades, but certainly
           | not  "much better". We absolutely need at least one language
           | that doesn't hide all that and I think the programming
           | language community as a whole will really benefit from the
           | list of choices for that being expanded from "C++", which is
           | getting _really_ long in the tooth And I 'm not even sure C++
           | was ever really _designed_ to be this language, I think a lot
           | of it just sort of happened by default and it sort of backed
           | into this role, and frankly, it shows. Rust being _designed_
           | for this can 't hardly help but be nicer, even if we
           | completely ripped out the borrow checker aspect.
        
         | codegeek wrote:
         | I wanted to learn Go while working professionally with PHP and
         | Python. I loved the simplicity and syntax of Go overall. I
         | learned Go enough to build a small internal tool for our team
         | and it is Production ready (at least internally). Then I wanted
         | to learn Rust since it is so popular and always compared with
         | Go and the syntax made me lose interest. Rust may be amazing
         | and I will be more open minded to try later but it didn't spark
         | the interest. Superficial I know since the real power is in
         | functionality etc but just an anecdote from an amateur.
        
           | skrtskrt wrote:
           | Another point is just about the maturity of language and
           | libraries.
           | 
           | I started learning Rust recently and when searching how to do
           | some pretty basic stuff, the answers are like "well you used
           | to do this but now you do this and soon you'll be able to do
           | this but it's not stabilized"
           | 
           | I figure I'll just check back in 5 years, I don't have the
           | time or patience to be on the bleeding edge when I'm trying
           | to get things done.
        
             | codegeek wrote:
             | Good point. In software especially web world, I am usually
             | wary of tech that is not at least 10 years mature/old.
        
           | worik wrote:
           | Yes. Go is better unless you need the features of Rust.
        
         | sph wrote:
         | There's definitely a space for native languages that are not as
         | dense and performant possibly as Rust. I will trade some
         | readability when I need strict memory guarantees and use Rust,
         | but most of my time I'd like to use something readable and fun
         | to use, which Rust ain't.
         | 
         | I used to use Go, not much of a fan anymore, but I'm liking
         | Crystal a lot to fill this space. Eventually Zig when it's more
         | mature.
        
           | sbmthakur wrote:
           | Just started learning Go. If I may ask, why did you loose
           | interest in Go?
        
             | sph wrote:
             | Not enough syntax sugar, not functional enough, and a few
             | smaller papercuts.
             | 
             | It feels dry, like a humourless android. Not very fun to
             | write but probably the most pragmatic choice for the
             | problem. I prefer having fun when I program.
        
         | amelius wrote:
         | > Systems languages need to have lots of detail you just don't
         | need in higher level languages like Haskell or Python
         | 
         | True, but Rust is being used for a lot more than just system
         | programming, judging from all the "{ARBITRARY_PROGRAM} written
         | in Rust" posts here on HN.
        
         | hawski wrote:
         | I find that Rust tends to have code that goes sideways more
         | than downward. I prefer the latter and most C code bases, that
         | I find elegant are like that.
         | 
         | It is like that, because of all the chaining that one can do.
         | It is also just a feeling.
        
           | est31 wrote:
           | There are two upcoming features, let chains and let else, to
           | counter the sideways drift.
           | 
           | Sometimes it's also the formatter though that outputs
           | intensely sideways drifting code: https://github.com/rust-
           | lang/rust/blob/1.60.0/compiler/rustc...
        
             | UmbertoNoEco wrote:
        
               | est31 wrote:
               | While generally, yes, features are bloating up a
               | language, one could argue these two particular features
               | _reduce_ complexity. Like why am I forbidden to use  &&
               | in a if let? And why does _if let_ support both
               | irrefutable and refutable patterns but deconstructing
               | _let_ requires them to be irrefutable?
        
               | UmbertoNoEco wrote:
               | There is surely some "law" in some place of the internet
               | that says something like: "Every programming language
               | valid construction no matter how ugly,
               | obscure,verbose,old,etc will find its way to lots of
               | codebases". See C++.
        
               | estebank wrote:
               | Yes, John Carmack has said as much, at least in the
               | context of syntactically and semantically valid
               | constructs that are actually bugs making it into
               | codebases. What does that have to do with let chains and
               | let else?
        
               | UmbertoNoEco wrote:
               | The problem are not the new traits per se. The problem is
               | that the complexity of a language grows super-linearly
               | with the number of things added to it. There is beauty
               | (and productivity) in simplicity. When you need to do 2
               | things and there are 2 ways of doing each, now you have 4
               | different combinations. All languages are more or less
               | guilty of this (even those which promise "Just 1 way to
               | do things") but it is undeniable that Rust is joining C++
               | in the right side of the complexity Bell curve.
        
               | estebank wrote:
               | let else and let chains aren't new traits, they are
               | syntactical features that make things that people would
               | expect to work, Just Work(tm). People keep bringing up
               | the complexity of Rust (a valid argument to be made
               | there) but then point at some feature that is _removing
               | an arbitrary limitation_ from the language. And even for
               | cases where a new feature is being added, I can point at
               | the case of ? for error handling that _was_ a _new_
               | feature, that  "complicated" the language, but that _very
               | clearly_ improved the ergonomics of the language for
               | reading and writing. Should ? have been left in the
               | cutting floor because it didn 't look like anything else
               | and was a "redundant" feature?
               | 
               | Let me put it another way: what Rust feature would you
               | _remove_ to  "simplify" the language?
        
               | UmbertoNoEco wrote:
               | As I pointed here originally, you need to be very careful
               | about what you ADD to a language, because once the cat is
               | out of the bag there is no going back, people are going
               | to use that stuff. That's why I dont begrudge the
               | attitude of the golang maintainers to be very slow in
               | introducing stuff, because it is basically an
               | irreversible step.
               | 
               | I suppose every thing in Rust has a raison d'etre but you
               | pay with complexity that versatility. I think there is
               | space now for a modern, memory-safe, SIMPLE, systems
               | programming language. C has the backwards compatibility
               | problem (although I am still bullish on its future) and a
               | language like Zig never got any traction. Hopefully the
               | future will bring new, interesting stuff.
        
           | aaron_m04 wrote:
           | I have noticed this tendency as well.
           | 
           | To counteract it, I write exit-early code like this:
           | let foo_result = foo();         if let Err(e) = foo_result {
           | return Bar::Fail(e);         }         let foo_result =
           | foo_result.unwrap();         ...
        
             | gardaani wrote:
             | Early exit code would be easier to write if Rust supported
             | guard let.
        
               | veber-alex wrote:
               | its coming soon, already available on nightly.
               | let Some(x) = foo() else { return 42 };
        
               | klodolph wrote:
               | Like this?                   if let Ok(x) = my_func() {
               | // ...         }
               | 
               | Or do you mean something else?
        
             | ntoskrnl wrote:
             | I do this too, with a different spin on it:
             | let foo = match foo() {           Ok(foo) => foo,
             | Err(err) => return Err(err),       };
             | 
             | I was typing it out so often I made editor aliases `lmo`
             | and `lmr` for Option and Result
        
               | veber-alex wrote:
               | let me introduce you to the famous '?' operator.
               | 
               | The code above can be written as:                 let foo
               | = foo()?;
        
               | ntoskrnl wrote:
               | LOL you're right! I just pasted the template here, but my
               | defaults are mostly equivalent to plain old `?`. I don't
               | use the match if `?` would work.
        
             | metaltyphoon wrote:
             | Isn't that a good general practice todo? Exit early
        
             | mathstuf wrote:
             | Any reason why this wasn't preferred?                   let
             | foo_result = foo()             .map_err(Bar::Fail)?;
        
               | veber-alex wrote:
               | Bar::Fail is not wrapped in a Result type, so you can't
               | use '?' with it (on stable at least).
               | 
               | You can write it like this:                 let
               | foo_result = match foo() {         Ok(v) => v,
               | Err(e) => return Bar::Fail(e)       };
        
               | loeg wrote:
               | The result type is the return from Foo -- Bar::Fail does
               | not need to wrap Result. Foo is Result<T, E> and
               | map_err() would convert it to Result<T, Bar::Fail>. I
               | think GP's `map_err()?` is the most straightforward way
               | of writing this idea (and it's generally speaking how I
               | would suggest writing Rust code).
        
               | veber-alex wrote:
               | GP's code will return Result<_, Bar>, the original code
               | we are trying to fix just returns Bar.
        
               | loeg wrote:
               | If you are writing code to handle Results, it's going to
               | be a lot less painful to just return Result.
        
           | kzrdude wrote:
           | I think it's because of the expression focus. Isn't it easier
           | to make the code flow like a waterfall when it's imperative,
           | but is harder to reason about values and state.
        
         | dingoegret12 wrote:
         | I love Rust and use it everyday but the syntax bloat is
         | something I will never get over. I don't believe there's
         | nothing that could be done about it. There are all sorts of
         | creative grammar paths one could take in designing a language.
         | An infinite amount, in fact. I would really like to see
         | transpiler that could introduce term rewriting techniques that
         | can make some of that syntax go away.
        
           | TheSoftwareGuy wrote:
           | Rust has an extremely powerful macro system, have you tried
           | that?
        
             | alpaca128 wrote:
             | Rust macros are one of the more annoying features to me.
             | They're great at first glance but whenever I want to build
             | more fancy ones I constantly bump into limitations. For
             | example they seem to be parsed without any lookahead,
             | making it difficult to push beyond the typical function
             | call syntax without getting compiler errors due to
             | ambiguity.
        
               | inferiorhuman wrote:
               | Procedural macros have a peek function from the syn
               | crate. macro_rules macros can stuff this into the pattern
               | matching.
               | 
               | e.g.
               | 
               | https://turreta.com/2019/12/24/pattern-matching-
               | declarative-...
        
           | zozbot234 wrote:
           | "Creative" grammar introduces parsing difficulties, which
           | makes IDE tooling harder to build and less effective overall.
           | My overall guess is that Rust made the right choices here,
           | though one can endlessly bikeshed about specifics.
        
             | klodolph wrote:
             | Creative grammar can introduce parsing difficulties, but it
             | doesn't have to.
             | 
             | I've made a couple small languages, and it's easy to end up
             | lost in a sea of design decisions. But there are a lot of
             | languages that have come before yours, and you can look to
             | them for guidance. Do you want something like automatic
             | semicolon insertion? Well, you can compare how JavaScript,
             | Python[1], Haskell, and Go handle it. You can even dig up
             | messages on mailing lists where developers talk about how
             | the feature has unexpected drawbacks or nice advantages, or
             | see blog posts about how it's resulted in unexpected
             | behavior from a user standpoint.
             | 
             | You can also take a look at some examples of languages
             | which are easy or hard to parse, even though they have
             | similar levels of expressivity. C++ is hard to parse...
             | why?
             | 
             | You'd also have as your guiding star some goal like, "I
             | want to create an LL(1) recursive descent parser for this
             | language."
             | 
             | There's still a ton of room for creativity within
             | constraints like these.
             | 
             | [1]: Python doesn't have automatic semicolon insertion, but
             | it does have a semicolon statement separator, and it does
             | not require you to use a semicolon at the end of
             | statements.
        
               | pizza234 wrote:
               | > you can look to them for guidance. Do you want
               | something like automatic semicolon insertion? Well, you
               | can compare how JavaScript, Python[1], Haskell, and Go
               | handle it
               | 
               | You can't look at JavaScript/Python/Go (I don't know
               | about Haskell), because Rust is a mostly-expression
               | language (therefore, semicolons have meaning), while
               | JavaScript/Python/Go aren't.
               | 
               | The conventional example is conditional assignment to
               | variable, which in Rust can be performed via if/else,
               | which in JS/Python/Go can't (and require alternative
               | syntax).
        
               | klodolph wrote:
               | > You can't look at JavaScript/Python/Go (I don't know
               | about Haskell), because Rust is a mostly-expression
               | language (therefore, semicolons have meaning), while
               | JavaScript/Python/Go aren't.
               | 
               | I have a hard time accepting this, because I have done
               | exactly this, in practice, with languages that I've
               | designed. Are you claiming that it's impossible,
               | infeasible, or somehow impractical to learn lessons from
               | -- uhh -- imperative languages where most (but not all)
               | programmers tend to write a balance of statements and
               | expressions that leans more towards statements, and apply
               | those lessons to imperative languages where most (but not
               | all) programmers tend to write with a balance that tips
               | more in the other direction?
               | 
               | Or are you saying something else?
               | 
               | The fact that automatic semicolon insertion has appeared
               | in languages which are just so incredibly different to
               | each other suggests, to me, that there may be something
               | you can learn from these design choices that you can
               | apply as a language designer, even when you are designing
               | languages which are not similar to the ones listed.
               | 
               | This matches my experience designing languages.
               | 
               | To be clear, I'm not making any statement about
               | semicolons in Rust. If you are arguing some point about
               | semicolon insertion in Rust, then it's just not germane.
        
             | KptMarchewa wrote:
             | Tooling should not depend on code text, but on language's
             | AST.
        
               | nightski wrote:
               | I'm not an expert as I do not work on these tools but I
               | don't think IDEs can rely solely on ASTs because not all
               | code is in a compilable state. Lots of times things have
               | to be inferred from invalid code. Jetbrains tools for
               | example do a great job at this.
        
               | tripa wrote:
               | Comments tending to skip on being a part of the AST make
               | that harder.
        
           | darthrupert wrote:
           | Nim, which technically accomplishes all (I assume) of the
           | Rusty things that require syntax, manages to do it with quite
           | a lot nicer syntax.
        
             | ben-schaaf wrote:
             | Nim accomplishes memory safety using a garbage collector.
             | That's pretty dissimilar to rust and more comparable to go
             | or D.
        
               | cb321 wrote:
               | While tracing garbage collection is indeed _one possible_
               | automatic memory management strategy in Nim, the new
               | --mm:arc may be what darthrupert meant. See
               | https://uploads.peterme.net/nimsafe.html
               | 
               | Nim is choice. :-) {EDIT: As DeathArrow also indicated! }
        
               | avgcorrection wrote:
               | Reference counting is a form of garbage collection.
        
               | cb321 wrote:
               | Terminology in the field can indeed be confusing. In my
               | experience, people do not seem to call reference counted
               | C++ smart pointers "garbage collection" (but sure,
               | one/you might, personally).
               | 
               | "Automatic vs manual" memory management is what a casual
               | PL user probably cares about. So, "AMM" with later
               | clarification as to automation options/properties is, I
               | think, the best way to express the relevant ideas. This
               | is why I said "tracing GC" and also why Nim has recently
               | renamed its _--gc:xxx_ CLI flags to be _--mm:xxx_.
               | 
               | Whether a tracing collector is even a separate thread or
               | directly inline in the allocation code pathway is another
               | important distinction. To muddy the waters further, many
               | programmers often mean the GC _thread(s)_ when they say
               | "the GC".
               | 
               | What runtimes are available is also not always a "fixed
               | language property". E.g., C can have a tracing GC via
               | https://en.wikipedia.org/wiki/Boehm_garbage_collector and
               | you can get that simply by changing your link line (after
               | installing a lib, if needed).
        
               | avgcorrection wrote:
               | I see now that the GP wrote "a garbage collector" (not
               | the article). Oops! "A reference counting method" doesn't
               | roll off the tongue. So it appears that your nitpicking
               | was indeed appropriate.
        
               | DeathArrow wrote:
               | Nim allows you to chose what memory management method you
               | want to use in a particular piece of software. It can be
               | one of various garbage collectors, reference counting or
               | even no memory management. It allows you to use whatever
               | suits your needs.
        
               | avgcorrection wrote:
               | > > Nim accomplishes memory safety using a garbage
               | collector.
               | 
               | No memory management in Nim equals no memory safety
               | guarantees. Or no? Well in that case the statement above
               | is true.
        
               | cb321 wrote:
               | You can get management and safety with one of Nim's
               | modes, as per the peterme link in my sibling, if you
               | would like to learn more.
        
               | avgcorrection wrote:
               | I don't understand why you all are posting tedious
               | details and well actuallys when the original assertion
               | was (way back):
               | 
               | > Nim, which technically accomplishes all (I assume) of
               | the Rusty things that require syntax, manages to do it
               | with quite a lot nicer syntax.
               | 
               | Nim does not have something which gives _both_ memory
               | safety _and_ no ((tracing garbage collector) and /or
               | (reference counting)) _at the same time_. End of story.
               | 
               | The fact that Nim has an off-switch for its automatic
               | memory management is totally uninteresting. It hardly
               | takes any language design chops to design a safety-off
               | button compared to the hoops that Rust has to jump
               | through in order to keep its lifetimes in check.
        
               | cb321 wrote:
               | >Nim does not have something which gives
               | 
               | You are simply incorrect, appear unwilling to research
               | why/appear absolutist rather than curious, and have made
               | clear that what I think is "clarification" or "detail
               | expansion" you deem "tedious" or "nitpicking" while
               | simultaneously/sarcastically implicitly demanding more
               | details. That leaves little more for me to say.
        
               | avgcorrection wrote:
               | You have managed to point out that tracing garbage
               | collection and reference counting are indeed two ways to
               | manage memory automatically. Three cheers for your
               | illuminating _clarification_.
        
             | djur wrote:
             | I'm curious what that assumption is based on. Rust and Nim
             | are pretty different, and both of them have features that
             | the other doesn't even try to have.
        
               | j-james wrote:
               | This is an interesting comparison of memory semantics I
               | stumbled upon: https://paste.sr.ht/blob/731278535144f00fb
               | 0ecfc41d6ee4851323...
               | 
               | Nim's modern memory management (ARC/ORC) is fairly
               | similar to Rust. ARC functions by reference-counting at
               | compile time and automatically injecting destructors:
               | which is broadly comparable to Rust's ownership + borrow
               | checker.
               | 
               | (A big difference is that Nim's types are Copy by
               | default: this leads to simpler code at the expense of
               | performance. You have control over this, keeping memory
               | safety, with `var`, `sink`, and others, as highlighted in
               | the above link.)
               | 
               | https://nim-lang.org/blog/2020/10/15/introduction-to-arc-
               | orc...
               | 
               | For reference cycles (the big limitation of reference
               | counting), there's ORC: ARC + a lightweight tracing
               | garbage collector.
               | 
               | As I understand it Rust also cannot handle reference
               | cycles without manually implementing something similar.
               | 
               | https://nim-lang.org/blog/2020/12/08/introducing-orc.html
               | 
               | https://doc.rust-lang.org/book/ch15-06-reference-
               | cycles.html
        
           | sophacles wrote:
           | It's a pain to write all that boilerplate, I agree. I don't
           | think it's bloat though - I've been doing rust for a few
           | years now, and when I revisit old mostly forgoten code, I
           | love that boilerplate. I rarely have to do any puzzling about
           | how to infer what from the current file, it's just all right
           | there for me.
           | 
           | I feel this way about all the verbosity in rust - some of it
           | could likely be inferred, but but having it all written down
           | right where it is relevant is great for readability.
        
             | carlmr wrote:
             | That's true, I found this writing F# with an IDE vs reading
             | F# in a PR without IDE it really becomes easier to read if
             | you at least have the types on the function boundary.
             | 
             | F# can infer almost everything. It's easier to read when
             | you do document some of the types though.
        
             | worik wrote:
             | Having done a bit of C lately (lots in the past) and quite
             | a bit of Rust, Rust is not verbose!
             | 
             | The functional syntax the author of this (good) article
             | complains about is what this (long experience in procedural
             | C like languages) old programmer has come to love.
        
         | dhosek wrote:
         | Familiarity also alleviates the issue. I can remember when I
         | first encountered TeX in the 80s and Perl in the 90s and
         | thought the code looked like line noise and now I no longer see
         | that (even in Larry Wall-style use-all-the-abbreviations Perl).
        
           | sidlls wrote:
           | It alleviates the issue the way the frog doesn't notice in
           | the "boiling frog" fable. That is, not in a good way. The
           | cognitive load to parse and understand it is still there;
           | you're just not as aware of it distracting from other
           | matters. Some (me) would say it distracts from more important
           | things, like how units of code compose and what the purpose
           | of a program is.
        
           | cardanome wrote:
           | The problem is that familiarity needs to be maintained or you
           | can lose it. As someone that doesn't get to use Rust at my
           | day job that can be hard to keep fresh.
           | 
           | I only occasionally dabble in Rust in my free time and coming
           | back to a project of mine after months of not having used any
           | Rust, yeah lets just say that line noise made me prematurely
           | murder some of my pet-projects.
           | 
           | Sure it gets probably better with time but still it is a cost
           | that one pays.
        
           | riskable wrote:
           | > ...thought the code looked like line noise and now I no
           | longer see that
           | 
           | "I don't even see the code anymore. I just see blonde,
           | brunette, ..."
           | 
           | I myself have _just_ started to get like that with my
           | understanding of Rust:
           | 
           | "I don't even see the `impl<P: 'static, const PS: usize>
           | IndexMut<usize> for SomeThing<P, PS>` anymore. I just see a
           | mutable iterator."
        
         | jillesvangurp wrote:
         | Something like Kotlin but with a borrow checker might be the
         | ultimate in developer ergonomics for me. I sat down at some
         | point to wrap my head around Rust and ended up abandoning that
         | project due to a lack of time. And because it was hard. The
         | syntax is a hurdle. Still, I would like to pick that up at some
         | point but things don't look good in terms of me finding the
         | time.
         | 
         | However, Rust's borrow checker is a very neat idea and one that
         | is worthy of copying for new languages; or even some existing
         | ones. Are there any other languages that have this at this
         | point?
         | 
         | I think the issue with Rust is simply that it emerged out of
         | the C/C++ world and they started by staying close to its syntax
         | and concepts (pointers and references) and it kind of went down
         | hill from there. Adding macros to the mix allowed developers to
         | fix a lot of issues; but at the price of having code that is
         | not very obvious about its semantics to a reader. It works and
         | it's probably pretty in the eyes of some. But too me it looks
         | like Perl and C had a baby. Depending on your background, that
         | might be the best thing ever of course.
        
           | zozbot234 wrote:
           | Rust and Kotlin have very similar syntax. The main
           | differences are semantics-related, such as Kotlin relying on
           | GC.
        
           | cogman10 wrote:
           | The borrow checker doesn't really work without lifetime
           | annotations. When I see complaints about rust, that's seems
           | to be the thing most are talking about. The issue is the
           | notion of an object lifetime is a hard thing to express with
           | familiar type systems. It's an unfamiliar concept.
        
         | cies wrote:
         | Maybe we've reached the limits of the complexity we can handle
         | in a simple text-based language and should develop future
         | languages with IDEs in mind. IDEs can hide some of the
         | complexity for us, and give access to it only when you are
         | digging into the details.
        
           | robonerd wrote:
           | The problem with this premise is that by raising the bar for
           | any IDE that wants to support that language, you risk the
           | creation of an IDE monoculture.
        
             | xxpor wrote:
             | Is that as true any more with the language server model?
             | 
             | I'm not familiar enough with it to know how much is truely
             | in the protocol vs what the editor still has to do
             | themselves.
        
               | robonerd wrote:
               | LSPs are great, I think they've proven fairly easy to
               | integrate into many text editors. But consider something
               | like the Scratch programming language. How many editors
               | support Scratch? Once you stray from code-as-text, adding
               | support to old editors often becomes infeasible and the
               | effort needed to create new editors is a significant
               | barrier to entry.
        
           | flohofwoe wrote:
           | This just plasters over the underlying problem, which in case
           | of Rust is IMO that features that should go into the language
           | as syntax sugar instead are implemented as generic types in
           | the standard library (exact same problem of why modern C++
           | source code looks so messy). This is of course my subjective
           | opinion, but I find Zig's syntax sugar for optional values
           | and error handling a lot nicer than Rust's implementation of
           | the same concepts. The difference is (mostly): language
           | feature versus stdlib feature.
        
             | marcosdumay wrote:
             | Rust developers are doing an awesome job of identifying
             | those things and changing the language to meet it. Today's
             | Rust is much cleaner than it was 5 years ago (or 8 if you
             | count nightly).
             | 
             | But yes, there is still a lot of it.
             | 
             | Anyway, most of the noise comes from the fact that Rust is
             | a low level language that cares about things like memory
             | management. It's amazing how one is constantly reminded of
             | this by the compiler, what is annoying, but the reason it
             | doesn't happen on the alternatives is because they never
             | let you forget about that fact.
        
             | vlovich123 wrote:
             | I'm not familiar with zig. Can you give some examples to
             | illustrate your point?
        
               | flohofwoe wrote:
               | An optional is just a '?' before the type:
               | 
               | For instance a function which returns an optional pointer
               | to a 'Bla':                   fn make_bla() ?*Bla {
               | // this would either return a valid *Bla, or null
               | }
               | 
               | A null pointer can't be used accidentally, it must be
               | unwrapped first, and in Zig this is implemented as
               | language syntax, for instance you can unwrap with an if:
               | if (make_bla()) |bla| {             // bla is now the
               | unwrapped valid pointer         } else {             //
               | make_bla() returned null         }
               | 
               | ...or with an orelse:                   const bla =
               | make_bla() orelse { return error.InvalidBla };
               | 
               | ...or if you know for sure that bla should be valid, and
               | otherwise want a panic:                   const bla =
               | make_bla().?;
               | 
               | ...error handling with error unions has similar syntax
               | sugar.
               | 
               | It's probably not perfect, but I feel that for real-world
               | code, working with optionals and errors in Zig leads to
               | more readable code on average than Rust, while providing
               | the same set of features.
        
               | veber-alex wrote:
               | I don't see how that is all that different from Rust.
               | 
               | The main difference I see is that in Rust it will also
               | work with your own custom types, not just optional.
               | fn make_bla() -> Option<Bla> {         // this either
               | returns a valid Bla, or None       }            if let
               | Some(bla) = make_bla() {         // bla is now the
               | unwrapped valid type       } else {         // make_bla()
               | returned None       }
               | 
               | ..or with the '?' operator (early return)
               | let bla = make_bla().ok_or(InvalidBla)?;
               | 
               | ..or with let_else (nightly only but should be stable
               | Soon(tm))                 let Some(bla) = make_bla() else
               | { return Err(InvalidBla) }
               | 
               | ..or panic on None                 let bla =
               | make_bla().unwrap();
        
         | shadowofneptune wrote:
         | The same information can be communicated in different ways,
         | trading one form of noise for another. I have a personal
         | preference for Pascal-like or PL/I syntax. Instead of int *char
         | x or int&& x, there's x: _byte_ _ptr_ _ptr_. It 's more to type
         | and read, sure, but sometimes having an english-like keyword
         | really helps clarify what's going on.
        
           | robonerd wrote:
           | > _It 's more to type and read_
           | 
           | I wouldn't even say that. Using words (or multi-letter
           | symbols generally) may be more to type, but virtually
           | everybody uses editors with completion features and those
           | completion features tend to work better with words than
           | symbols. Furthermore, despite there being more characters, I
           | don't think it's actually more to read. People who are fluent
           | in reading languages written with alphabet systems don't read
           | letter-by-letter, but instead read word-by-word, using
           | effortless word recognition.
        
             | jnwatson wrote:
             | Typing words is faster than symbols for most folks even
             | without an IDE. Typing `&{% takes way longer than "static
             | long foo".
        
             | zozbot234 wrote:
             | > People who are fluent in reading languages written with
             | alphabet systems don't read letter-by-letter, but instead
             | read word-by-word, using effortless word recognition.
             | 
             | It all adds up. Languages like COBOL, PASCAL or ADA
             | (originally designed for terminals with very limited
             | character sets, sometimes even lacking lowercase text -
             | thus requiring case-insensitive syntax) make it a lot
             | harder to survey larger code blocks.
        
               | robonerd wrote:
               | > _It all adds up._
               | 
               | If that's true, I would expect logographic writing
               | systems to cause less reader fatigue than alphabetic
               | writing system. But as far as I'm aware that isn't the
               | case, and the two are roughly equivalent.
        
           | nu11ptr wrote:
           | I agree, and my ideas for alternative syntax were effectively
           | this. They were, in my opinion, a slight improvement, but
           | still result in lots of syntax. My point is that while I
           | might want a more "python-like" or "ML-like" syntax we often
           | forget that it simply isn't possible in the same way those
           | languages use it, and by the time we add all the extra things
           | we need, it doesn't look that much less "noisy".
        
           | Banana699 wrote:
           | The english words preference is a cliche that has been argued
           | back and forth, to heaven and hell, since Cobol. I'm
           | sympathetic to your opinion in some cases, but ultimately it
           | fails in my view. Terse notations requires an investment in
           | the beginning but then pay off massively with increased
           | bandwidth, you can hold more of the code in your head. You
           | don't see math being done by (x.plus(y)).pow(3), you see it
           | done by (x+y)^3, it gets even worse when expressions increase
           | in size.
           | 
           | Ideally, the language should have enough syntax-bending
           | facilities so that you can still simulate what you want, this
           | is mostly just operator overloading and not treating custom
           | types like second class citizens. For example, your example
           | of byte ptr ptr can be easily done in C++ by a bytePtrPtr
           | struct, or even better, a Ptr<Ptr<Byte>> instantiated class
           | from the template Ptr<T> for any T. Overloading the
           | dereference and conversion operators will completely hide any
           | trace of the fact it's not a built in type, and compiler
           | optimization and inlinning will (hopefully, fingers crossed)
           | ensure that no extra overhead is being introduced by the
           | abstraction.
           | 
           | As for the 'byte ptr ptr' syntax specifically, in F# generic
           | instantiation can be done by whitespace concatenation of type
           | names in reversed C++/Java/C# order, so the above C++ type
           | would (if translated to F# somehow) literally be written out
           | as you want it to be, so even what seems like it would
           | require language support (whitespace between related
           | identifiers, generally a tricky thing in PL design) can
           | actually be accomplished with clever and free minded syntax.
        
             | shadowofneptune wrote:
             | That is a good point about typedefs, and I would hate to be
             | using 'ADD 1, a, b TO x ROUNDED' instead of 1 + a + b +
             | round(x). I'll also have to check out F#.
        
         | singularity2001 wrote:
         | I think making things syntactically explicit which are core
         | concepts is stupid:
         | 
         | ```pub fn horror()->Result{Ok(Result(mut &self))}```
         | 
         | A function returns a Result. This concept in Rust is so
         | ubiquitous that it should be a first class citizen. It should,
         | under all circumstances, be syntactically implicit:
         | 
         | ```pub fn better->self```
         | 
         | No matter what it takes to make the compiler smarter.
        
           | dllthomas wrote:
           | Others have addressed the problem with "implicit", but I
           | might be on board with "lightweight"; maybe in a type context
           | `T?` can mean `Result<T>` for whatever Result is in scope?
           | That way you can still define functions with various distinct
           | error types the same as today, but the common (idk just how
           | common, not claiming a majority) case of using the same error
           | across a module or package with a Result type alias will get
           | cleaner.
        
           | dragonwriter wrote:
           | > A function returns a Result.
           | 
           | That is not, in fact, a core concept in Rust. Plenty of
           | functions have no reason to return Result. (And some that do
           | also have a reason for the inner class to be a result.)
           | 
           | > This concept in Rust is so ubiquitous that it should be a
           | first class citizen. It should, under all circumstances, be
           | syntactically implicit:
           | 
           | "Implicit" is an opposed concept to "first-class citizen".
           | Result is first-class in Rust, and would not be if function
           | returns were implicitly Result.
        
             | jherico wrote:
        
               | dragonwriter wrote:
               | > I remain convinced that the whole Result concept was
               | just created by people butt-hurt over the concept of
               | exceptions
               | 
               | I wouldn't use the emotionally-loaded dismissive
               | language, but, yes, Result is a solution to the same
               | problem as exceptions that deals with several problems of
               | exceptions, including:
               | 
               | (1) Unchecked exceptions obscure what is going on, and
               | frustrate analysis because things remote from the code
               | may bypass it in the call-stack without any evidence
               | visible in signatures.
               | 
               | (2) Checked exceptions are clear, but create a separate
               | syntax for expressing type-like constraints, also
               | limiting what you can do around them _because_ they aren
               | 't the same thing as types.
               | 
               | Results are basically cleaner checked exceptions.
        
               | jherico wrote:
               | I'll certainly grant that unchecked exceptions are
               | problematic for static analysis, but in regards to your
               | second point, I don't feel like Rust has actually avoided
               | creating "a separate syntax". It's created a different,
               | more complex syntax which must be adopted inline in your
               | actual normal code path, obfuscating what your code is
               | actually expected to do under non-error conditions.
               | 
               | IMO, one of the most valuable pieces of exception
               | handling is a distinct separation between your error
               | logic and your non-error logic, which makes methods
               | easier to comprehend. I also feel like the existence of
               | the ? syntax is a dead giveaway in this regard because
               | it's a fig-leaf trying to cover up the most egregious
               | parts of the code where you'd otherwise have to be write
               | the frequent "if error then early return error"
               | statements which plague Golang.
        
             | singularity2001 wrote:
             | > Result is not a core concept in Rust.
             | 
             | If you don't see std::result::Result as a core concept in
             | Rust, which might be fair, one can still argue that it
             | _should_ be a core concept, given its ubiquitous usage.
        
               | dragonwriter wrote:
               | You misquoted, I never said Result is not a core concept.
               | 
               | What I said is that "A function returns Result" in the
               | universal sense (that is, everything that is a function
               | returns Result) is not a core concept in Rust.
               | 
               | Some functions return Result<T,E> for some <T,E>. Some
               | functions return Option<T> for some T. Some functions
               | have no reason to use that kind of generic wrapper type
               | (a pure function that handles any value in its range and
               | returns a valid value in a simple type for each doesn't
               | need either; Option/Result are typically needed with
               | otherwise non-total functions or functions that perform
               | side effects that can fail.)
        
           | pcwalton wrote:
           | This would break the principle that you always know how to
           | invoke a function by looking at its signature. Option of T
           | and Result of T are not the same type as T. You would have to
           | look at the body of the function, or rustdoc, to know how to
           | invoke it, which would be very annoying.
           | 
           | Besides, what is the error type for Result? You haven't
           | declared it.
        
         | runevault wrote:
         | Your summary is the thing I struggle with as well. How do you
         | deal with the issues of density without either making it more
         | verbose by a wide margin (which also hampers readability) or
         | hiding information in a way that makes the code less obvious
         | which is, IMO, worse.
         | 
         | Software is becoming more and more complex and unless there are
         | entirely different design patterns we have failed to find,
         | managing and understanding that during both the writing and the
         | maintenance of software is the fundamental problem of our time.
         | Someone else in these comments mentioned leaning more heavily
         | into IDE tooling and I do wonder if we are coming to a point
         | where that makes sense.
        
           | ModernMech wrote:
           | > unless there are entirely different design patterns we have
           | failed
           | 
           | It's not that we've failed to find different design patterns,
           | it's that we found these patterns in the 70s and haven't done
           | much with them since. Since C there has been a pretty
           | constant march toward more imperative programming, but
           | imperative programming I feel has reached its peak for the
           | reasons you describe.
           | 
           | We're only _just_ starting to explore the functional
           | programming space and incorporate those learnings into our
           | work. But what about logic programming, dataflow programming,
           | reactive programming, and other paradigms that have been
           | discovered but not really fully explored to the extent
           | imperative programming has been? I think there's a lot of
           | room for improvement just by revisiting what we've already
           | known for 50 years.
        
         | api wrote:
         | IMHO it's at least somewhat better than "modern" C++ where you
         | end up having to wrap virtually every single thing in some kind
         | of template class, and that's without the benefit of much
         | stronger memory and thread safety.
         | 
         | Overall I think Rust is a hands-down win over C and C++. People
         | who want it to be like Go are probably not doing systems-level
         | programming, which is what Rust is for, and I have severe
         | doubts about whether a rich systems-level language could be
         | made much simpler than Rust and still deliver what Rust
         | delivers. If you want full control, manual memory management
         | with safety, other safety guarantees, a rich type system, high
         | performance, and the ability to target small embedded use
         | cases, there is a certain floor of essential complexity that is
         | just there and can't really be worked around. Your type system
         | is going to be chonky because that's the only way to get the
         | compiler to do a bunch of stuff at compile time that would
         | otherwise have to be done at runtime with a fat runtime VM like
         | Go, Java, C#.NET, etc. have.
         | 
         | Go requires a fat runtime and has a lot of limitations that
         | really hurt when writing certain kinds of things like high
         | performance codecs, etc. It's outstanding for CRUD, web apps,
         | and normal apps, and I really wish it had a great GUI story
         | since Go would be a fantastic language to write normal level
         | desktop and mobile UI apps.
        
           | Night_Thastus wrote:
           | For what purpose would you need to wrap everything in a
           | template class? In my work, I've only touched templates a
           | couple of times in years. They're useful, but I don't see how
           | it's always needed.
        
             | ben-schaaf wrote:
             | std::unique_ptr and std::shared_ptr are templated wrapper
             | classes.
        
               | Night_Thastus wrote:
               | Oh. I misunderstood. I was thinking of user-made
               | templates, not the built-in ones from the standard
               | library. I don't see the issue though. Something like
               | vector feels intuitive. I have a vector<int> or a
               | vector<myType> etc. A pointer to an int, a
               | unique_ptr<int>. It's convenient and fairly flexible. I
               | don't really see the downside, or how it could be done
               | better given static typing.
        
         | queuebert wrote:
         | Completely agree. I think of the extra syntax as us helping the
         | compiler check our code. I have to write a few more characters
         | here and there, but I spend _way_ less time debugging.
         | 
         | Although I may have PTSD from Rust, because lately I find
         | myself preferring Qbasic in my spare time. -\\_(tsu)_/-
        
           | agumonkey wrote:
           | Probably a very general response to overload of any kind..
           | you start to reevaluate the opposite side of the spectrum.
        
             | smegsicle wrote:
             | the dialectical method
        
               | agumonkey wrote:
               | I'd have used the 'banging on both guard rails but yours
               | sounds better.
        
         | singularity2001 wrote:
         | >>> I'm not convinced much could have been done about it.
         | 
         | Are you sure? What stops Swift with its beautiful syntax and
         | safe optionals from becoming a systems language?
        
           | tayistay wrote:
           | Perhaps not that that much. Swift's arrays are refcounted.
           | And you can't store an array on the stack. Classes are
           | refcounted too, but you could avoid them. It also has a bit
           | of a runtime, and you don't know when it will take locks or
           | allocate (though there is work to tag functions so they can't
           | do either).
        
         | pjmlp wrote:
         | System languages on the Algol/Wirth branch prove otherwise.
         | 
         | They can be ergonomic high level, while providing the language
         | features to go low level when needed.
        
           | titzer wrote:
           | Agree, and even C got really far without traits. Traits are a
           | lot of rope for building confusing abstractions, IMHO.
        
       | ducktective wrote:
       | About the installation method ('hi! download this random shell
       | script and execute it'), I agree this is really dangerous but
       | mere installing stuff is a hairy thing on linux distros. I mean
       | what is the practical alternative? Distro package manager
       | versions are almost always way behind.
       | 
       | NixOS/guix are gonna solve this issue once and for all (famous
       | last words)
        
         | mjw1007 wrote:
         | Here are some things that they could do better:
         | 
         | - the domain in the curlbashware URL could be less shady than
         | sh.rustup.rs
         | 
         | - the "rustup is an official Rust project" claim on
         | https://rustup.rs/ could be a link to a page somewhere on rust-
         | lang.org that confirms that rustup.rs is the site to use
        
           | pmoriarty wrote:
           | _" the domain in the curlbashware URL could be less shady
           | than sh.rustup.rs"_
           | 
           | Relying on a familiar looking domain doesn't get you much
           | security, especially with internationalized domain names
           | where what a domain name appears like in one language could
           | actually be very different in another.
        
             | marcosdumay wrote:
             | I imagine people type that string on their terminals.
             | Pasting things there is full of issues, and it's not long.
        
           | __ryan__ wrote:
           | - the domain in the curlbashware URL could be less shady than
           | sh.rustup.rs
           | 
           | The domain is only as shady as it is unfamiliar. It's not
           | shady to me since I recognize it as the canonical domain of
           | the recommended installer for Rust, "rustup".
           | - the "rustup is an official Rust project" claim on
           | https://rustup.rs/ could be a link to a page somewhere on
           | rust-lang.org that confirms that rustup.rs is the site to use
           | 
           | It links to rust-lang.org, whose installation page then
           | describes rustup as the recommended way to install [0]. I
           | suppose it could link directly to the page, but what really
           | does that gain?
           | 
           | 0: https://www.rust-lang.org/tools/install#rustup
        
             | amalcon wrote:
             | It's shady because it's under the TLD for Serbia, while
             | having no obvious connection to Serbia. I have nothing
             | against Serbia, but the Rust project doesn't seem to have
             | any special relationship to that country.
             | 
             | In HN and similar places, it is pretty normal to see a cc-
             | tld used purely because the abbreviation fits. Not everyone
             | is used to that, though. If it were e.g.
             | https://rustup.dev/, that would mitigate this concern.
        
               | __ryan__ wrote:
               | By that logic https://github.io is _shady_.
               | 
               | Also, a bad actor could just as well register
               | https://rustup.dev. Rather than judging a URL in a vacuum
               | based on the TLD, you should instead cross reference the
               | official docs and confirm that the URL is correct.
        
               | amalcon wrote:
               | Is it not? If GitHub were asking me to download and run
               | code from a github.io subdomain without checking a
               | signature, or something of similar risk level, I'd be
               | concerned. I'd also be _correct_ to be concerned, since
               | anyone can put anything in a github.io subdomain -- I 'd
               | need to make sure that github actually owns that repo.
               | Strictly speaking that's orthogonal, and github does
               | actually own the github.io domain. The domain still seems
               | suboptimal to me, but I don't make those decisions.
               | 
               | And yes, a bad actor could just as easily register
               | rustup.dev. Nobody ever claimed that checking the TLD is
               | sufficient to make a site trustworthy; only that it
               | appears a bit shady. Unless you're already familiar with
               | Rust (or at least with a particular aspect of startup
               | culture), there's no obvious reason to choose .rs. On the
               | other hand, domains in somepopularsite.unrelatedtld have
               | been a phishing staple for decades -- making the shady
               | vibe at least a little bit reasonable.
        
               | __ryan__ wrote:
               | I meant that the logic implies that https://github.io is
               | shady _because_ it uses the ccTLD of British Indian Ocean
               | Territory despite being unrelated.
               | 
               | Of course you should cross reference the authenticity of
               | any URL you are about to execute as a shell script. No
               | one is saying not to.
               | 
               | But your point seems to agree with mine: it's only as
               | shady as it is unfamiliar. The answer shouldn't be to
               | come up with a URL that lowers your guard. Instead, users
               | should get familiar.
        
         | maccard wrote:
         | But it's not really dangerous, no more so than downloading an
         | arbitrary binary and executing it at least. The script is
         | delivered over https, so you're not going to be MITM'ed, and
         | you're trusting rustup to provide you the valid install script.
         | If you _are_ MITM'ed, it doesn't really matter what your
         | delivery method is unless you do a verification from another
         | device/network, and if you don't trust rustup then why are you
         | downloading and executing their installer?
        
           | ducktective wrote:
           | If they `shellcheck` their bash script, then sure. Aside from
           | unquoted $vars, usually random shell scripts have a habit of
           | polluting home and creating arbitrary dirs under god-knows-
           | where and not respecting XDG.
           | 
           | They are almost always irreversible too. Like you can't undo
           | the steps the shell scripts have done.
        
             | __ryan__ wrote:
             | _Any_ software you choose to run could not respect your
             | desires and leave a mess. This is not a random shell
             | script. It 's the officially recommended way to install
             | Rust [0], vetted and maintained by the community. You're
             | free to audit the script before running it, or even check
             | out the source [1]. If this doesn't satisfy you, check out
             | the other installation methods [2].
             | 
             | Edit: I realize you're not speaking specifically about
             | rustup, but what I said can and should apply to anything
             | you choose to install this way.
             | 
             | 0: https://www.rust-lang.org/tools/install#rustup
             | 
             | 1: https://github.com/rust-lang/rustup
             | 
             | 2: https://forge.rust-lang.org/infra/other-installation-
             | methods...
        
               | marcosdumay wrote:
               | > Any software you choose to run could not respect your
               | desires and leave a mess.
               | 
               | On most languages, you must decide to do it to create a
               | mess. Bash is almost alone on the place where you can do
               | it by accident.
        
               | maccard wrote:
               | A syntax error in any scripting language will have the
               | exact same problem.
        
               | marcosdumay wrote:
               | Problems like removing a large directory instead of a
               | file, creating your files on random places instead of the
               | directory you pass on, or creating more files than you
               | intended?
               | 
               | The one mess you see from other languages is creating
               | files on the wrong place (or all over the place). But not
               | those above.
        
               | maccard wrote:
               | > Problems like removing a large directory instead of a
               | file
               | 
               | rm doens't do that unless you explicitly tell it to.
               | 
               | > Problems like removing a large directory instead of a
               | file, creating your files on random places instead of the
               | directory you pass on, or creating more files than you
               | intended?
               | 
               | But yes, all of these can and do exist in other
               | languages. Using python as an example, if you read an
               | environment variable without checking it's set (as in the
               | infamous steam bug) [0], you'll end up with pretty much
               | the exact same behaviour. You can misindent your loop in
               | python and not create/remove files that you intend to, or
               | your script can have a syntax error halfway through and
               | the interpreter will happily proceed until it halts, and
               | leave you in a half baked state just like bash does.
               | 
               | [0] https://github.com/valvesoftware/steam-for-
               | linux/issues/3671
        
               | __ryan__ wrote:
               | Any tool can be dangerous in inexperienced or careless
               | hands. The issues you described could just as likely be
               | caused by logic errors or typos in any other language.
               | 
               | You're talking as if all bash scripts are hacked together
               | carelessly and work by accident. You can actually _learn_
               | bash. Thankfully the script we're discussing is written
               | with care and vetted by the community.
               | Problems like removing a large directory instead of a
               | file
               | 
               | The _rm_ command doesn't even remove directories by
               | default, you have to specify a flag. Not knowing a tool
               | is not a good reason to bash it.
        
               | marcosdumay wrote:
               | Isn't Rust one of those languages based on the idea that
               | tools matter and that should either be correct or
               | obviously wrong?
               | 
               | (And no, those problems do usually not appear due to
               | logic errors or typos in other languages. It's very, very
               | rare.)
               | 
               | I'm well aware that the Rust installation script is well
               | vetted and stable enough to be reliable. Bootstraping a
               | development environment is also a real problem, with no
               | good answers. It's understandable that they want to
               | bootstrap from Bash. But as understandable as it is, it
               | still carries the Bash issues with it.
               | 
               | Of course, the optimum solution would be to do it from
               | your system's tools. That is something that will probably
               | happen naturally given enough time.
        
               | maccard wrote:
               | > Isn't Rust one of those languages based on the idea
               | that tools matter and that should either be correct or
               | obviously wrong?
               | 
               | It doesn't really matter, if you combine `/home/myuser`
               | and some unsantized input variable, and then call
               | `remove_dir_all` [0], it doesn't matter how safe the
               | language is, you're going to delete your entire home
               | directory with absolutely no warning, whether it's in
               | bash, go, python, rust or haskell. Yes bash makes this
               | very easy to do, but so does pretty much every language
               | in existence.
               | 
               | > (And no, those problems do usually not appear due to
               | logic errors or typos in other languages. It's very, very
               | rare.)
               | 
               | They absolutely do. Here's an explosive script in golang
               | (deliberately doesn't compile just in case) - running
               | this in func main() will ruin your day most likely.
               | dirToRemove := "~/" + os.Getenv("BAD_ENV_VAR")
               | os.RemoveAll(dirToRemove
               | 
               | I can write one of these in bash, python, go, you name
               | it.
               | 
               | [0] https://doc.rust-
               | lang.org/std/fs/fn.remove_dir_all.html
        
             | maccard wrote:
             | The same can be said for any badly written python script,
             | or golang binary too.
        
         | IshKebab wrote:
         | > this is really dangerous
         | 
         | People repeat this a lot but really it just _seems_ dangerous.
         | Can you give an example of a scenario where offering a download
         | via `curl | bash` is more dangerous than  "download this
         | installer with the hash 01234 and then execute it"?
        
           | ben0x539 wrote:
           | The site could detect that it's invoked as part of a `curl |
           | bash` and sometimes serve a different script than you would
           | get if you manually downloaded the script or the installer
           | for manual inspection/auditing, making it harder to detect
           | shenanigans. I think someone wrote this up as a PoC/blog post
           | at some point.
        
         | otterley wrote:
         | > NixOS/guix are gonna solve this issue once and for all
         | (famous last words)
         | 
         | Should we take bets on whether this happens first, or whether
         | nuclear fusion becomes mainstream first?
        
       | NoGravitas wrote:
       | > This is a superficial complaint, but I found Rust syntax to be
       | dense, heavy, and difficult to read.
       | 
       | I'm not sure this _is_ a superficial complaint. People say the
       | hard thing about learning Rust is the new concepts, but I haven
       | 't found that to be true at all. The concepts are easy, but the
       | combinatorial explosion of syntax that supports them is
       | untenable.
        
         | gxt wrote:
         | I use rust weekly and I find it to have the best DX. I have
         | done work with Oracle Java 5-8, IBM XL C99, MSVC++11, CPython
         | 2-3, C# .NET Core 3.1. Stable Rust 2021 is overall the most
         | readable, least surprising, BUT only with the right tool which
         | also makes it the most discoverable, with rust-analyzer. My
         | only gripe is the lack of consensus on strongly typed error
         | handling (anyhow+thiserror being the most sensible combination
         | I found after moving away from bare Results, to failure, to
         | just anyhow).
        
         | kkoning wrote:
         | > but the combinatorial explosion of syntax that supports them
         | is untenable.
         | 
         | I wouldn't go quite that far myself, but it's definitely one of
         | the sharper edges of the language currently--particularly
         | because some of the features don't work together yet. E.g.,
         | async and traits.
        
         | devit wrote:
         | How would you change the syntax?
         | 
         | I don't think that Rust has much redundant syntax.
         | 
         | I guess you could do things like replace &'a Type with Ref<'a,
         | Type> and *Type with Ptr<Type>, and get rid of some sugar like
         | "if let" and print!, but I'm not sure that would have much of
         | an impact.
        
         | sidlls wrote:
         | Back when I wrote C and C++ for a living I'd occasionally meet
         | someone who thought their ability to employ the spiral rule or
         | parse a particularly dense template construct meant they were a
         | genius. I get the same vibe from certain other groups in this
         | industry, most recently from functional programmers and Rust
         | afficionados, for example. Nobody gives a damn if you can
         | narrate a C spiral or a functional-like Rust idiom.
         | 
         | And this syntax density is one of the reasons I stopped
         | advocating for the use of Rust in our systems. First, I don't
         | want to work with languages that attract this kind of person.
         | Second, I don't want to work with languages that require a
         | relatively heavy cognitive load on simply reading the lines of
         | the source code. Units of code (i.e. statements, functions,
         | structures and modules) are _already_ a cognitive load--and the
         | more important one. Any extra bit I have to supply to simply
         | parsing the symbols is a distraction.
         | 
         | "You get used to it," "with practice it fades to the
         | background," etc. are responses I've seen in these comments,
         | and more generally when this issue comes up. They're inaccurate
         | at best, and often simply another way the above mentioned
         | "geniuses" manifest that particular personality flaw. No, thank
         | you. I'll pass.
        
           | bbkane wrote:
           | If not C++ or Rust, what languages do you advocate for now?
        
             | sidlls wrote:
             | Depends on the application, really. And I wouldn't call it
             | "advocacy" so much as being resigned to accepting a less
             | odious bad option. In that case, typically Go or Python,
             | unless we need that last bit of performance and can't get
             | it with a pre-built library: then I'd argue for C, C++, and
             | Rust (in that order).
        
             | pjmlp wrote:
             | Not the OP, I rather use managed languages with AOT/JIT
             | toolchains.
             | 
             | C++ and Rust I leave for scenarios where choice is imposed
             | on me due to platform SDKs, or having any kind of automatic
             | memory management isn't an option.
        
               | jgilias wrote:
               | Rust's memory semantics are definitely a kind of
               | 'automatic memory management' though. I mean, that's the
               | whole premise - to have the kind of guarantees about
               | memory safety that until Rust where only available in
               | GC'ed languages running on some runtime.
        
               | pjmlp wrote:
               | There is nothing automatic about compiler errors in
               | lifetimes.
               | 
               | As for until Rust, Cyclone and ATS did it first.
        
           | duped wrote:
           | > I get the same vibe from certain other groups in this
           | industry, most recently from functional programmers and Rust
           | afficionados, for example.
           | 
           | Another trait in programmers that is worth avoiding is the
           | false equivalency between C++ template metaprogramming and
           | generic programming in languages with expressive static
           | typing.
           | 
           | It's not clever or inscrutable like templates, quite the
           | opposite. It's explicit about constraint. Generic Rust makes
           | it easier to understand complex code and write it correctly.
           | An immediate red flag for me are programmers who don't "get
           | it" because they equate that to some kind of SFINAE or
           | compile time magic they once saw in C++. They're not the same
           | feature, except superficially.
        
           | mmarq wrote:
           | > I don't want to work with languages that attract this kind
           | of person
           | 
           | I haven't used Rust professionally, but I find the community
           | extremely inclusive and helpful. I joined the Discord server
           | and asked all sorts of stupid questions and people always
           | helped me and explained to me what was wrong with my code (or
           | my assumptions). But, again, I haven't used Rust
           | professionally and it may be different in that context
           | 
           | > I don't want to work with languages that require a
           | relatively heavy cognitive load on simply reading the lines
           | of the source code
           | 
           | Strongly agree on this, I haven't tried to introduce it where
           | I work for the same reason. The cognitive load is massive
           | compared to a language like C# or JS and the gain is minimal
           | for the average developer writing microservices for React
           | frontends. In this context you need a JSON serializer,
           | iterators and maybe generics, and Rust is not much better
           | than C# on this front.
        
           | rr808 wrote:
           | > And this syntax density is one of the reasons I stopped
           | advocating for the use of Rust in our systems.
           | 
           | Trouble is I've found this type of genius is most languages.
           | There are always some esoteric functionality that few people
           | understand that some people will choose because its "the most
           | appropriate" but largely because its a challenge. Of course
           | such talented people move on to the next project quickly as
           | maintaining their crap is not fun.
        
           | epage wrote:
           | > Back when I wrote C and C++ for a living I'd occasionally
           | meet someone who thought their ability to employ the spiral
           | rule or parse a particularly dense template construct meant
           | they were a genius. I get the same vibe from certain other
           | groups in this industry, most recently from functional
           | programmers and Rust afficionados, for example. Nobody gives
           | a damn if you can narrate a C spiral or a functional-like
           | Rust idiom.
           | 
           | I think one problem is dealing with "just because you can
           | doesn't mean you should". It is easy to be nerd-sniped into
           | optimizing everything in Rust. I've seen complain about an
           | arg parser using dynamic dispatch when anything the program
           | actually does will dwarf the time that that takes. I feel we
           | need a reset; a stdlib-alternative that optimized for those
           | learning and prototyping at the cost of performance. I
           | suspect people using that will help break them of the feeling
           | to optimize the trivial but to instead focus on what
           | profilers tell them.
        
           | voidhorse wrote:
           | I'm with you. I think people that treat syntax as some
           | completely unimportant detail are forgetting that reading
           | code is a more important use case than writing code.
           | 
           | No matter how much you internalize the syntax of language X,
           | as the sheer number of syntactic structures in the language
           | increases, the higher the likelihood you'll misread
           | something.
        
           | robonerd wrote:
           | > _I get the same vibe from certain other groups in this
           | industry, most recently from functional programmers and Rust
           | afficionados_
           | 
           | Perl one-liner guys used to exemplify this. But I don't
           | really agree that functional programmers do, except for
           | Haskell and people who use lots of the car and cdr
           | compositions, or those who use too much metaprogramming,
           | or... okay maybe you're right. But at least the fundamental
           | premise of functional programming is simple..
        
           | nonameiguess wrote:
           | I don't use Rust a ton, certainly not enough that the syntax
           | density fades into the background, but something I'll say for
           | the ecosystem is rust-analyzer is really good and pretty much
           | always knows and warns you when you're writing something
           | incorrectly that won't compile. The worst parts of the syntax
           | effectively become self-writing, though it does nothing to
           | help reading.
        
           | scythe wrote:
           | >Second, I don't want to work with languages that require a
           | relatively heavy cognitive load on simply reading the lines
           | of the source code. Units of code (i.e. statements,
           | functions, structures and modules) are already a cognitive
           | load--and the more important one. Any extra bit I have to
           | supply to simply parsing the symbols is a distraction.
           | 
           | The weird thing about these comments to me (as someone who
           | doesn't use Rust) is that the most difficult syntax in the
           | original examples represents a _semantic_ detail that most
           | languages don 't have to deal with: the _lifetime_. The
           | amount of times I think about the lifetimes of variables I
           | write in Python is zero. Parsing the symbols and
           | understanding the code here aren 't separate; that weird
           | apostrophe thing in angle brackets is a symbol I don't use
           | referencing a concept I don't use, which fits. If you
           | replaced the symbols with keywords or something, it would
           | just be longer, not simpler.
           | 
           | Also, it's a choice to write your code like he did. You can
           | define local variables that hold intermediate results and
           | subexpressions and give them descriptive names, if you want.
           | You could assign `drop = (|_| ())` for example.
        
         | krupan wrote:
         | One human needs to figure out how to write a line of code once,
         | and then that line needs to be read and understood by humans
         | over and over.
         | 
         | Optimize for readability. Rust doesn't seem to do this.
        
           | ModernMech wrote:
           | It's hard to optimize for readability, performance, and
           | safety. Rust chose to go with performance and safety. In the
           | future, maybe we can have a language that gives all three but
           | not today.
        
             | verdagon wrote:
             | Shameless relevant plug: that's the exact goal of Vale! [0]
             | 
             | It turns out, when one removes the borrow checker, they get
             | something that's much more readable, because a lot of
             | Rust's complexity was added to help support the borrow
             | checker.
             | 
             | Ironically, we can then add back in a different, easier
             | form of borrow checking to get the speed benefits.
             | 
             | [0] https://vale.dev/
        
               | NoGravitas wrote:
               | Vale looks exciting. Thanks for the link.
        
               | quirino wrote:
               | It's refreshing to see such a simple, good-looking and
               | informative website. Also incredibly fast! Please keep it
               | that way.
        
               | vrfvr wrote:
               | > Rust is also very difficult. It's as complex as C++,
               | and throws it all at the programmer at once.
               | 
               | I thin Rust isnt nearly as complex
        
             | eternalban wrote:
             | Same thing that happened with type declarations will need
             | to happen to semantic intent: inference.
        
           | estebank wrote:
           | Readability seems to mean different things to different
           | people. You (and many others!) seem to interpret that word as
           | "there's only relevant information and nothing else in
           | sight". Personally I interpret it as "I have all the relevant
           | information available to me in a way I can scan for quickly".
           | Rust has a higher syntactic load, there are more things
           | present to the reader, but it also means that everything the
           | reader _might_ need is always available, and the syntactical
           | patterns are unique enough that it is  "easy" (we can argue
           | this point forever) to skip things you don't care about. When
           | I look at type signatures, sometimes I care about the trait
           | bounds, sometimes I don't. Sometimes I care about the
           | lifetime relationship between different arguments and the
           | output, sometimes I don't. Languages that make these
           | relationships completely implicit make it easy to focus on
           | _some_ aspects of the code 's behavior, while obscuring
           | others.
        
         | UmbertoNoEco wrote:
         | Correct, this is more or less like remarking that having to
         | learn Kanji/Hanzi makes learning Japanese/Mandarin very
         | difficult is a superficial complaint.
        
         | titzer wrote:
         | I find Rust code hard to read...to the point where I don't feel
         | motivated to learn it anymore. Line noise is confusing and a
         | distraction. Random syntactic "innovations" I find are just
         | friction in picking up a language.
         | 
         | For example, in the first versions of Virgil I introduced new
         | keywords for declaring fields: "field", "method" and then
         | "local". There was a different syntax for switch statements, a
         | slightly different syntax for array accesses. Then I looked at
         | the code I was writing and realized that the different keywords
         | didn't add anything, the array subscripting syntax was just a
         | bother; in fact, all my "innovations" just took things away and
         | made it harder to learn.
         | 
         | For better or for worse, the world is starting to converge on
         | something that looks like an amalgam of Java, JavaScript, and
         | Scala. At least IMHO; that's kind of what Virgil has started to
         | look like, heh :)
        
         | perrygeo wrote:
         | It's not a superficial complaint but it is _relative_ to one 's
         | experience. Something that's "difficult" for me might be "easy"
         | for you and vice versa. I find it very much related to
         | understanding the core concepts.
         | 
         | I personally find Rust syntax to be quite enjoyable, or at
         | least it fades into the background quickly - with a few
         | exceptions. The syntax for lifetime annotations can be
         | challenging. And not surprisingly explicit lifetime annotations
         | are a rather unique concept, at least among mainstream
         | languages. IOW the syntax is difficult because it's an entirely
         | new mental model (for me), not because `<'a>` is an inherently
         | bad way to express it.
        
       | jmartin2683 wrote:
       | Rust is awesome. I've been in love since the moment I met it.
        
       | tommyage wrote:
       | I did not read the post, but scanned for the first contra-
       | argument: A very dense syntax. This is the reason Rust did not
       | attract me.
       | 
       | I want to raise the following: Rust is overengineered. If these
       | highly-intelligent contributors would settle on D, I think
       | humanity/developer-community would archive more collaborations on
       | essential pieces of software.
       | 
       | Imo a statically-typed language is required to develop
       | maintainable code. Human communications, read documentation, is
       | much easier to extend than compilation-restrictions of a
       | programming language.
       | 
       | What are the non-fixable downsizes, which prevent serious
       | adaptation of D?
       | _readsupuponthepostbecauseaCcomparsionwasspotted_
       | 
       | My personal opinion is: The convenience of tooling. Currently I
       | am developing a language agnostic language server, which aims to
       | be integrated in unix environmets without requiring exorbitant
       | memory (currently 8 MB + file-contents). I feel, that this is my
       | only contribution I can submit to the community iff I suceed.
        
       | SemanticStrengh wrote:
       | Let me takes this opportunity to explain that among the many
       | contraints of rust, it is the undertalked one about the absurd no
       | cast promotion from smaller integer (e.g. a char) to a bigger
       | integer that made me quit and save my sanity. Having to make
       | explicit casts a dozen times per functions for basic
       | manipulations of numbers on a grid (and the index type mismatch)
       | is an insult to the developer intelligence. It seems some people
       | are resilient and are able to write nonsensical parts of code
       | repeatedly but for me, I can't tolerate it.
        
         | josephg wrote:
         | I don't mind a few "as usize" casts because usually you can
         | cast once and be done with it. But the cast that kills me is
         | this one:
         | 
         | How do you add an unsigned and a signed number together in
         | rust, in a way which is fast (no branches in release mode),
         | correct and which panics in debug mode in the right places (if
         | the addition over- or under-flows)? Nearly a year in to rust
         | and I'm still stumped!
        
           | steveklabnik wrote:
           | https://rust.godbolt.org/z/e377o5148 is the first thing I
           | thought of.
           | 
           | You didn't specify sizes, or if you wanted the result to be
           | signed or unsigned, but "assume two's compliment wrapping in
           | release and panic in debug on over/underflow" is the default
           | behavior of +.
        
             | mjw1007 wrote:
             | That fails the "panics in debug mode in the right places"
             | requirement:
             | 
             | https://play.rust-
             | lang.org/?version=stable&mode=debug&editio...
        
               | steveklabnik wrote:
               | Oh duh, yeah, my bad. I was tweaking stuff around and
               | lost that property. And seems like TryInto doesn't
               | compile away entirely. Boo.
               | 
               | You can write your own debug_assert! though:
               | https://play.rust-
               | lang.org/?version=stable&mode=debug&editio...
               | 
               | not as nice, but it does work. If you were doing this a
               | lot you could macro it up, impl as a method on all the
               | various types you want... a pain, but it is possible.
        
         | allisdust wrote:
         | Considering all the type casting bugs prevalent in other
         | languages, I would have more trust in the compiler than
         | programmers at this point. You can always pick javascript of
         | course, which happily returns you what ever it feels like.
         | Frankly this explicit casting makes the next developer's life
         | easier.
        
           | SemanticStrengh wrote:
           | completely off topic, a smaller type to a larger type can
           | never be an issue.
        
             | yencabulator wrote:
             | _When_ the invisible conversion happens changes the end
             | result. It can still be very tricky.
        
               | SemanticStrengh wrote:
               | E.g on function parameters. It's always pass by copy,
               | there can't be an issue.
        
       | voidhorse wrote:
       | I wholeheartedly agree that rust's syntax is way noisier and
       | uglier than I'd like, and it's nice to see someone else raise the
       | point seriously. People tend to act like syntax is an ancillary
       | detail in a language, but actually it's fundamental! It's our
       | direct interface into the language itself and if it's painful to
       | read and write the language won't be pleasant to use, no matter
       | how great it's semantics may be.
       | 
       | Beyond the line noise problem. I feel some of rust's syntactic
       | choices are confusing. For instance:
       | 
       | let x = 2
       | 
       | Introduces a new name and binds it to the value 2 while
       | 
       | if let Some(x) = y
       | 
       | Is a shorthand for pattern matching. Meanwhile other matching
       | structures have no need of "let" at all. Likewise this extends
       | the semantics of what "if" means and also overloads "=" (e.g,
       | glancing at this, would you say equals is binding a value to a
       | pattern, performing a Boolean check, or both?) Rust has a couple
       | of one-off weird syntactical devices that have been introduced as
       | shorthand that imo quickly increase the cognitive load required
       | to read code because several structures and keywords are reused
       | in slightly different ways to mean entirely different things.
       | 
       | There are a lot of similar syntactic hoops around type signatures
       | because they didn't go with the old "type variables must be
       | lowercase" rule which leads to subtle potential ambiguities in
       | parsing T as a variable or proper type in some cases that thus
       | forces additional syntax on the user.
       | 
       | I also think there are too many ways to express equivalent things
       | in Rust, which again leads to more cognitive overhead. Reading
       | the current docs, I get the sense the language is becoming "write
       | biased". Whenever they introduce some syntactic shortcut the
       | justification is to save typing and eliminate small amounts of
       | repetition, which is great in theory but now we have N ways of
       | writing and reading the same thing which quickly makes code hard
       | to grok efficiently imo.
       | 
       | This minor gripe comes with the big caveat that it remains
       | probably the most interesting language to become vogue since
       | Haskell.
        
         | irishsultan wrote:
         | > For instance:
         | 
         | > let x = 2
         | 
         | > Introduces a new name and binds it to the value 2 while
         | 
         | > if let Some(x) = y
         | 
         | > Is a shorthand for pattern matching.
         | 
         | Both introduce a new name (x) and both pattern match, it's just
         | that the pattern in let x = 2 is simply match anything and
         | assign it the name x, you could just as well write
         | 
         | let t@(x, y) = (2, 4);
         | 
         | Which binds t to (2, 4), x to 2 and y to 4 and there it's
         | perhaps more clear that normal let is pattern matching as much
         | as if let is pattern matching.
        
         | burntsushi wrote:
         | It might help you to think of 'if let' as an extension of 'let'
         | rather than an extension of 'if'. That is, 'let' by itself
         | supports irrefutable patterns. e.g.,                   let
         | std::ops::Range { start, end } = 5..10;
         | 
         | So the 'if' is "just" allowing you to also write _refutable_
         | patterns.
        
           | preseinger wrote:
           | That's fine but it's nonintuitive.
        
             | burntsushi wrote:
             | It is to me.
        
           | voidhorse wrote:
           | That is a useful way to think about it for sure, I'm mostly
           | using it as an illustration of what is probably a
           | philosophical difference between myself and the Rust
           | maintainers; in other words, I don't see why we need if let
           | when we already have match with _ wildcards. It's the sort of
           | syntactic shortcut that gives authors of code relatively
           | little benefit (save a few keystrokes) and readers of code
           | yet one more syntactic variation to contend with.
           | 
           | I guess another way of putting it is that I think Rust has a
           | lot of sugar that's confusing.
           | 
           | Kotlin is an example of a language that has a lot of similar
           | syntactic shortcuts and functional underpinnings that
           | implements them in a more readable and consistent fashion
           | imo.
        
             | burntsushi wrote:
             | I could live without 'if let'. I'm not a huge fan of it
             | either, although I do use it.
             | 
             | Its most compelling benefit to me is not that it saves a
             | few keystrokes, but that it avoids an extra indentation
             | level. Compare (taking from a real example[1]):
             | if let Some(quits) = args.value_of_lossy("quit") {
             | for ch in quits.chars() {                 if !ch.is_ascii()
             | {                     anyhow::bail!("quit bytes must be
             | ASCII");                 }                 // FIXME(MSRV):
             | use the 'TryFrom<char> for u8' impl once we are
             | // at Rust 1.59+.                 c =
             | c.quit(u8::try_from(u32::from(ch)).unwrap(), true);
             | }         }
             | 
             | with:                   match args.value_of_lossy("quit") {
             | None => {}             Some(quits) => {                 for
             | ch in quits.chars() {                     if !ch.is_ascii()
             | {                         anyhow::bail!("quit bytes must be
             | ASCII");                     }                     //
             | FIXME(MSRV): use the 'TryFrom<char> for u8' impl once we
             | are                     // at Rust 1.59+.
             | c = c.quit(u8::try_from(u32::from(ch)).unwrap(), true);
             | }             }         }
             | 
             | The 'for' loop is indented one extra level in the latter
             | case. With that said, I do also use 'if let' because it
             | saves some keystrokes. Taking from another real example[2],
             | compare:                   if let Some(name) =
             | get_name(group_index) {             write!(buf, "/{}",
             | name).unwrap();         }
             | 
             | with                   match get_name(group_index) {
             | None => {}             Some(name) => {
             | write!(buf, "/{}", name).unwrap();             }         }
             | 
             | (I could use '_ => {}' instead of 'None' to save a few
             | more.)
             | 
             | I do find the 'if let' variant to be a bit easier to read.
             | It's optimizing for a particular and somewhat common case,
             | so it does of course overlap with 'match'. But I don't find
             | this particular overlap to be too bad. It's usually pretty
             | clear when to use one vs the other.
             | 
             | But like I said, I could live without 'if let'. It is not a
             | major quality of life enhancement to me. Neither will its
             | impending extensions. i.e., 'if let pattern = foo &&
             | some_booolean_condition {'.
             | 
             | [1]: https://github.com/BurntSushi/regex-
             | automata/blob/fbae906823...
             | 
             | [2]: https://github.com/BurntSushi/regex-
             | automata/blob/fbae906823...
        
               | saurik wrote:
               | I don't code in Rust--and thereby might be expected to
               | not know all of these patterns and want to have to learn
               | fewer bits--and yet I agree with you. I feel like
               | removing this "if let" variant would be similar to saying
               | we don't need if statements as they are equivalent to a
               | loop that ends in break. I actually even will say the if
               | let is much easier to read as with the match I have to
               | check why it is a match and verify it has the None case--
               | similar to checking if a loop is really going to loop or
               | if it always ends in break--whereas I can skip all that
               | work if I see the "if".
        
         | beltsazar wrote:
         | > I feel some of rust's syntactic choices are confusing. For
         | instance:
         | 
         | > let x = 2
         | 
         | > Introduces a new name and binds it to the value 2 while
         | 
         | > if let Some(x) = y
         | 
         | > Is a shorthand for pattern matching.
         | 
         | It won't be as confusing once you realize that both do the same
         | thing: variable binding. The difference is that the former is
         | an irrefutable binding, whereas the latter is a refutable
         | binding.
         | 
         | Suppose that we have:                   struct Foo(i32);
         | 
         | A few more examples of irrefutable binding:
         | 
         | 1. As a local variable:                   let Foo(x) = Foo(42);
         | 
         | 2. As a function parameter:                   fn bar(Foo(x):
         | Foo) {}
        
         | ntoskrnl wrote:
         | I'm overall a rust fan but I've always agreed with you about
         | `if let`. What I don't like is that it reads right-to-left and
         | starts getting awkward if either side is much longer than just
         | a variable name.                 if let Some(Range { start, end
         | }) = self.calc_range(whatever, true) {           // ...       }
         | 
         | I feel it would read much smoother if you switched the two
         | sides so execution flows left-to-right                 if
         | self.calc_range(whatever, true) is Some(Range { start, end }) {
         | // ...       }
        
           | mpawelski wrote:
           | Agree, this is something that I wish was changed and it's
           | something that C# got right. I think I tried to look up why
           | this syntax was chosen and found some old github issues when
           | people were actually suggesting the latter syntax (pattern on
           | the right) and I think there were some syntax ambiguities in
           | this syntax. Not sure if this was the main reason. Maybe the
           | lang team just didn't thought the difference is important
           | enough (and it is for me! ;-)). C# lang designers think about
           | IDE experience when designing language syntax (that's why we
           | have "from", "where", "select" order in LINQ, for better IDE
           | code completion), hope other language designers were more
           | thoughtful about it too.
        
           | metaltyphoon wrote:
           | Agreed and that' how C# does pattern matching on `if`
        
         | avgcorrection wrote:
         | Conservative Java has something similar with try-with-resource
         | and the upcoming instanceof pattern matching.
        
       | ArdelleF wrote:
       | We do a lot of Rust compilation exploration during the
       | development of TiKV(github.com/tikv/tikv), a lot of interesting
       | learnings ... https://en.pingcap.com/blog/rust-huge-compilation-
       | units/
        
         | SemanticStrengh wrote:
         | thanks for maintaining jemalloc :)
        
       | cmrdporcupine wrote:
       | Good article. I have some things to say, because that's what I
       | do.
       | 
       | To start: I have to say that I find some of the comments here a
       | little odd -- the competition for Rust is not Go or TypeScript or
       | Kotlin or whatever. If you're using Rust in your full-stack
       | webdev world to serve, like, database queries to webpages or
       | whatever... I don't know why. Rust is clearly for things like:
       | writing an OS, writing a browser, writing a low latency high
       | throughput transaction server, writing a game. For the other
       | things I'd say there's plenty of other options. It's been years
       | since I worked in web applications, but I struggle to see the
       | need for Rust there.
       | 
       | Rust is for the same niche that C++ and C sit in now. A similar
       | niche that Zig is targeting. I don't think D with its <admittedly
       | now optional> GC or Golang sit in this same space _at all_. Also,
       | having spent a year working in Go I don 't understand how anybody
       | could complain about Rust encouraging boilerplate but propose Go
       | with a straightface. Go (at least the Go I was working on at
       | Google) was just a pile of boilerplate. Awful. The syntax of the
       | language is... fine. Generics will fix most of my complaints with
       | it. The _culture_ around the language I found repulsive.
       | 
       | Anways, for years (prior to C++-11) I whined about the state of
       | C++. Not just its lack of safety but the idiosyncracies of its
       | syntax and its lack of modern language features I was familiar
       | with from e.g. OCaml and from hanging out on Lambda The Ultimate.
       | By modern features I mean pattern matching & option / result
       | types, lambdas, type inference, and a generics/parameterized type
       | system which wasn't ... insane. Remember, this is pre-C++11. It
       | was awful. C++-11 and beyond addressed some concerns but not
       | others. And I actually really love writing in C++ these days, but
       | I'm still well aware that it is a dogs breakfast and full of foot
       | guns and oddities. I've just learned to think like it.
       | 
       | Anyways, back to Rust...before C++11, when I saw Graydon Hoare
       | had kickstarted a project at Mozilla to make a systems
       | programming language (that is without a GC) that supported modern
       | language features I was super stoked. I tended to follow what
       | Graydon was doing because he's talented and he's a friend-of-
       | friends. Rust as described sounded like exactly what I wanted.
       | But the final delivery, with the complexities of the borrow
       | checker... are maybe something that I hadn't gambled on. Every
       | few months I give another wack at starting a project in Rust and
       | every few months I tend to run up against the borrow checker with
       | frustration. But I think I have it licked now, I think I will
       | write some Rust code in my time off work.
       | 
       | So my personal take on Rust is this: on _paper_ it 's the fantasy
       | language I always wanted, but in _reality_ it has many of the
       | complexity warts that other people have pointed to.
       | 
       |  _However_ it is better than all the alternatives (other than
       | maybe Zig) in this space in many many ways. But _most
       | importantly_ it seems to have gained momentum especially in the
       | last 2-3 years. It seems clear to me now that the language will
       | have success. So I think systems developers will probably need to
       | learn and  "love" it just like they do C/C++ now. And I don't
       | think that's a bad thing because I think a culture will build up
       | that will get people up to speed and some of the syntactical
       | oddities just won't look that odd anymore. And the world of
       | software dev will hopefully be a bit safer, and build systems
       | less crazy, and so on.
        
       | bilkow wrote:
       | It looks like I'm on the minority here, but I generally like
       | Rust's syntax and think it's pretty readable.
       | 
       | Of course, when you use generics, lifetimes, closures, etc, all
       | on the same line it can become hard to read. But on my experience
       | on "high level" application code, it isn't usually like that. The
       | hardest thing to grep at first for me, coming from python, was
       | the :: for navigating namespaces/modules.
       | 
       | I also find functional style a lot easier to read than Python,
       | because of chaining (dot notation) and the closure syntax.
       | 
       | Python:                   array = [1, 0, 2, 3]         new_array
       | = map(             lambda x: x * 2,             filter(
       | lambda x: x != 0,                 array             )         )
       | 
       | Rust:                   let array = [1, 0, 2, 3];         let
       | new_vec: Vec<_> = array.into_iter()             .filter(|&x| x !=
       | 0)             .map(|x| x * 2)             .collect();
       | 
       | I mean, I kind of agree to the criticism, specially when it comes
       | to macros and lifetimes, but I also feel like that's more
       | applicable for low level code or code that uses lots of features
       | that just aren't available in e.g. C, Python or Go.
       | 
       | Edit: Collected iterator into Vec
        
         | the__alchemist wrote:
         | I think part of this comes down to: Does your Rust code make
         | heavy use of generics? I find myself deliberately avoiding
         | generics and libraries that use them, due to the complexity
         | they add. Not just syntactic noise, but complicated APIs that
         | must be explicitly documented; rust Doc is ineffective with
         | documenting what arguments are accepted in functions and
         | structs that use generics.
         | 
         | See also: Async.
        
           | klabb3 wrote:
           | > See also: Async.
           | 
           | Ah, the good ole generic, nested, self-referencing,
           | unnameable state machine generator.
        
         | klodolph wrote:
         | There are people who write Python code like that, but it's an
         | extreme minority. Here's the more likely way:
         | array = [1, 0, 2, 3]         new_array = [x * 2 for x in array
         | if x != 0]
         | 
         | Just as a matter of style, few Python programmers will use
         | lambda outside something like this:                   array =
         | [...]         arry.sort(key=lambda ...)
        
           | bilkow wrote:
           | I guess you're right, list/generator comprehensions are the
           | idiomatic way to filter and map in python, with the caveat of
           | needing to have it all in a single expression (the same goes
           | for lambda, actually).
           | 
           | I still feel like chained methods are easier to
           | read/understand, but list comprehensions aren't that bad.
        
             | Iwan-Zotow wrote:
             | > with the caveat of needing to have it all in a single
             | expression (the same goes for lambda, actually).
             | 
             | one could use multiple expressions in lambda in (modern)
             | Python
        
               | vgel wrote:
               | Do you mean using the walrus operator? Because unless I
               | missed a recent PEP, I don't know of a way to do this
               | without something hacky like that.
        
             | dralley wrote:
             | Even in Rust I don't like chains that go beyond ~4
             | operations. At some point it becomes clearer when expressed
             | as a loop.
        
         | nemothekid wrote:
         | 1. I don't think your Python example if fair. I think
         | new_array = [x*2 for x in array if x != 0]
         | 
         | is much more common.
         | 
         | 2. In your example, `new_array` is an iterator; if you need to
         | transform that into an actual container, your rust code
         | becomes:                  let new_array = array.into_iter()
         | .filter(|&x| x != 0)             .map(|x| x * 2)
         | .collect::<Vec<_>>();
         | 
         | And there your generic types rear their ugly head, compared to
         | the one liner in python.
        
           | saghm wrote:
           | I generally just write it like this:                  let
           | new_array: Vec<_> = array.into_iter()
           | .filter(|&x| x != 0)             .map(|x| x * 2)
           | .collect();
           | 
           | I'm actually a bit confused by the `&x` given that
           | `into_iter()` is used, which would take ownership of the
           | array values, but assuming that it was supposed to be just
           | `iter()` (or that it's an array of &i32 or something I
           | guess), you're going to be copying the integer when
           | dereferencing, so I'd probably just use `Iterator::copied` if
           | I was worried about too many symbols being unreadable:
           | let new_array: Vec<_> = array.iter()             .copied()
           | .filter(|x| x != 0)             .map(|x| x * 2)
           | .collect();
           | 
           | There's also `Iterator::filter_map` to combine `filter` and
           | `map`, although that might end up seeming less readable to
           | some due to the need for an Option, and due to the laziness
           | of iterators, it will be collected in a single pass either
           | way:                  let new_array: Vec<_> = array.iter()
           | .copied()             .filter_map(|x| if x == 0 { None } else
           | { Some(x * 2) })             .collect();
           | 
           | This is definitely more verbose than Python, but that's
           | because the syntax needs to disambiguate between owned and
           | copied values and account for static types (e.g. needing to
           | annotate to specify the return type of `collect`, since you
           | could be collecting into almost any collection type you
           | want). It's probably not possible to handle all those cases
           | with syntax as minimal as Python, but if you are fine with
           | not having fine-grained control over that, it's possible to
           | define that simpler syntax with a macro! There seem to be a
           | lot of these published so far
           | (https://crates.io/search?q=comprehension), but to pick one
           | that supports the exact same syntax in the Python example,
           | https://crates.io/crates/comprende seems to do the trick:
           | let array = [0, 1, 2, 3];         let new_array = c![x * 2
           | for x in array if x != 0];         println!("{:?}",
           | new_array); // Prints [2, 4, 6]
           | 
           | I'm not trying to argue that Rust is a 1:1 replacement to
           | Python or that if Python suits your needs, you shouldn't use
           | it; I think it's worth pointing out that Rust has more
           | complex syntax for a reason though, and that it has
           | surprisingly good support for syntactic sugar that lets you
           | trade some control for expressiveness that can alleviate some
           | of the pain you might otherwise run into.
        
             | bilkow wrote:
             | It actually needs the & in both my example and your second
             | example, because .filter receives a reference to the item
             | being iterated. Your second example doesn't compile:
             | https://play.rust-
             | lang.org/?version=stable&mode=debug&editio...
        
           | veber-alex wrote:
           | They maybe rear their ugly head but they also allow you to
           | collect the iterator into any collection written by you, by
           | the standard library or by any other crate.
           | 
           | While in python you have list/dict/set/generator
           | comprehension and that's it.
        
             | nemothekid wrote:
             | I don't think it's bad thing. In fact one of my favorite
             | features is that you can do `.collect::<Result<Vec<_>,
             | _>>()` to turn an interators of Results, into a Result of
             | just the Vec if all items succeed or the first error. That
             | is a feature you just can't express in Python.
             | 
             | But you have to admit that is a pretty noisy line that
             | could be difficult to parse.
        
               | dralley wrote:
               | Then don't write it that way.                  let
               | new_array: Vec<usize> = array.into_iter()
               | .filter(|&x| x != 0)             .map(|x| x * 2)
               | .collect();
               | 
               | Isn't so bad.
        
               | nemothekid wrote:
               | I believe I have the habit of putting it on the end
               | because the final type might be different. Consider:
               | let array = ["DE", "AD", "BE", "EF"];         let
               | new_array: Vec<u32> = array.into_inter()
               | .map(|x| u32::from_str_radix(x, 16))
               | .collect()?;
               | 
               | In this case you need to specify the Result generic type
               | on generic. This has come up for me when working with
               | Stream combinators. Most projects probably end up in
               | needing some lifetime'd turbofish and you have to be able
               | to parse them. They aren't rare enough, IME, to argue
               | that Rust isn't noisy.
        
           | bilkow wrote:
           | Oh, yeah, you're right! If you want to collect into a Vec you
           | may need to specify the type, but usually, you can just call
           | `.collect()` and the compiler will infer the correct type (as
           | I suppose you're collecting it to use or return).
           | 
           | If it can't infer, it's idiomatic to just give it a hint (no
           | need for turbofish):                   let new_vec: Vec<_> =
           | array.into_iter()             .filter(|&x| x != 0)
           | .map(|x| x * 2)             .collect();
           | 
           | I don't think that's ugly or unreadable.
           | 
           | About the Python list comprehension, I answered your sibling,
           | I think you're both right but it also does have it's
           | limitations and that may be personal, but I find chained
           | methods easier to read/understand.
        
       | fmakunbound wrote:
       | > It's 2022 after all, and transistors are cheap: why don't all
       | our microcontrollers feature page-level memory protection like
       | their desktop counterparts?
       | 
       | I always thought it was because of the added cost from increased
       | design complexity. Is it something else?
        
         | bunnie wrote:
         | Secretly, I suspect the answer is market differentiation. You
         | can charge a higher royalty for a CPU core that has an MMU, and
         | bundling it into the low end stuff erodes margins.
         | 
         | The complexity is real, but in a typical SoC the actual CPU
         | core is maybe 10% of the area and tossing in an MMU impacts
         | maybe 1-2% of the total chip area. I haven't seen the pricing
         | sheets, but I suspect the much bigger cost is the higher
         | royalty payment associated with instantiating the MMU.
        
       ___________________________________________________________________
       (page generated 2022-05-19 23:00 UTC)