[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)
 
web link (www.bunniestudios.com)
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
| . After this command completes the vendor directory
| specified by  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, 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(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          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         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 and
        | map_err() would convert it to Result. 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
    | IndexMut for SomeThing` 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 {         // 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> instantiated class
    | from the template Ptr 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` 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 for some . Some
        | functions return Option 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 or a
        | vector etc. A pointer to an int, a
        | unique_ptr. 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, 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 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 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  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::>();
  | 
  | 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::,
      | _>>()` 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 = 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 = 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)