Live data from Hacker News

Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

opensource.googleblog.com

181–190 of 233 posts

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#181

Earlier quoted context omitted.

Is there any Rust outfit out there that doesn't discourage macro use? For that matter, is there any team with a language out there that encourages macro use when working as a team?

I've never seen a team that encouraged writing new macros to solve routine problems. But I've certainly been on teams that made heavy use of a few carefully deployed macros to solve recurring problems specific to that codebase. I think elixir's sigils are probably the closest thing I've seen to "routine, encouraged macro use." Since almost every application will end up with a bit of template lite almost-dsl pseudo la…

I think Elixir is a bad example here because it's one of the eco systems that, while they preach "Use a function if you can!" very loudly, use macros much more heavily than other eco systems, often in places where they don't have to. Phoenix, the (unfortunate) flagship library, abuses macros all over the place where even relative beginners can see that they didn't need to (see [0] for example). It's incredibly badly designed overall and these things have set the tone (especially since a lot of Elixir programmers are in reality just Phoenix programmers).

So, while macros are "discouraged" in Elixir, in practice they are very much encouraged by several prominent libraries. Picking on Phoenix is very easy because it's so blatantly bad in this regard (and others) but it's almost impossible to do useful things with Ecto if you go outside the macro bubble, etc., as well.

Example that shows how an eco system that definitely could have done stuff with macros (Clojure) has correctly decided that writing functions that take data is better than using macros:

Elixir and `Plug.Router`:

    defmodule MyRouter do
      use Plug.Router
    
      plug :match
      plug :dispatch
    
      get "/hello" do
        send_resp(conn, 200, "world")
      end
    
      forward "/users", to: UsersRouter
    
      match _ do
        send_resp(conn, 404, "oops")
      end
    end

Clojure and `reitit` (https://github.com/metosin/reitit):

    (def router
      (r/routes
        [["/hello" {:get (fn [r] {:status 200 :body "world"})}]
         ["/users" {:name :users
                    :router users-router}]
         ["*" {:get (fn [r] {:status 404 :body "oops"})}]]))
P.S. I've used Elixir since 2015, this is not an opinion I've developed at a glance.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#182

Earlier quoted context omitted.

The "simplicity" of C is not a good thing. The Brainfuck language is even "simpler" and you can read the spec in 2 minutes. But that does not make it easier, because all the complexity is in the usage. The abstraction layer that one can build with rust allow the programmer to actually focus of the actual business logic instead of trying to get low level details right.

I think you missed the part about systems programming. When you are programming real hardware, the focus is entirely on low level details. You need to know the commands being sent to the device, the device state, and the ownership of resources by the device (which Rust doesn't solve for) are correct. The innovation of Rust is the borrow checker, which is primarily of interest to systems programmers. If your primary i…

> there are tools that don't require manual memory management or being pedantic about the different types of strings. You could just use Go, Java, Haskell, Python, etc.

1. Rust doesn't force you to do manual memory management. Rust memory management is automatic by default and only if you really, really want to, you can do it manually.

2. Memory is not the only resource. The GCs in languages you listed only solve the memory management problem, but regarding the other types of resources, their ergonomics are often worse than C - you have to remember to close the resources manually and you get virtually no help from the compiler.

3. None of the listed languages address problems related to concurrency, e.g. data races. Ok, Haskell kinda avoids the problem by imposing other restrictions - by not allowing mutation / side effects ;)

4. Rust offers way better tools for building high level abstractions than Go, Python and Java. It has set a very high bar with algebraic data types, pattern matching, traits/generics and macros.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#183

> Rumor 5: Rust code is high quality – Confirmed! > The respondents said that the quality of the Rust code is high — 77% of developers were satisfied with the quality of Rust code. Well, that’s exactly what I’d expect Rust developers to say. Nobody loves Rust more than Rust adopters. Would be interesting to see more objective measures of code quality (e.g. defect rate) Also, the type of person to work on a Rust codeb…

People used to say "when people are forced to use Rust at their job, they'll start hating it, only hobbyists use it and that's why it's so beloved." Do you really consider people learning Rust on the job to be "Rust adopters" who are partisan? Is anyone who ever uses Rust a "Rust adopter" who is unable to give an unbiased opinion? Who would be able to give that opinion, in your view?

> As an engineering manager...

> unbiased opinion

If the engineering manager after putting so much effort into switching to Rust, and trying to convince upper levels, putting their head at risk and after busting balls for months to make everyone learn Rust, comes into the office one day and asks if we love Rust, we the 77% that want to keep our jobs would answer "OF COURSE WE DO!!!!! COULDN'T BE HAPPIER!!!", with a big smile.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#184
post #107

Earlier quoted context omitted.

While you are technically right, one area where the two are unlike is that you want to be polymorph with regards to async/non-async, while it is less often the case for error handling. That exact same sleep implementation, or db query should be usable both as an async call, as well as a blocking one and it is the caller that wants to decide that. Which is not trivial to do on the calling side from a language perspect…

> While you are technically right, one area where the two are unlike is that you want to be polymorph with regards to async/non-async, while it is less often the case for error handling. The reason why we don't want to be polymorphic between fallible and “infallible” functions is that we put a clear social hierarchy between “properly handle error cases” and “panicking”. Using panics instead of `Result` make error han…

Let’s not make this discussion so rust-specific — panics are not used that way in rust for a reason. But exceptions (especially checked exceptions like in java) don’t have that problem, and are exact analogues to Result types. The point is, some way or another that parse function can fail and you may want to handle it. The caller can easily decide that from afar.

This is not true of async/blocking — there can be semantic differences between two, otherwise equivalent implementations, and it is a recursive problem as I mentioned — how should an async-block-async call chain work exactly? Java can decide it at runtime, while rust with its tradeoffs meaningfully can’t - but it is a net negative tradeoff in its case.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#185
post #30

> Low-level Operating Systems Sr. User Experience Researcher Wow, I didn't even know this job existed. IMO Rust as a C++ replacement is fine, Rust as a C replacement has more trade-offs than I still care to make. C is still far simpler (you can still read K&R in one day and keep most of the language in your head), has faster compile times, and the pain points cough macros are still often pain points in Rust. I think…

The "simplicity" of C is not a good thing. The Brainfuck language is even "simpler" and you can read the spec in 2 minutes. But that does not make it easier, because all the complexity is in the usage. The abstraction layer that one can build with rust allow the programmer to actually focus of the actual business logic instead of trying to get low level details right.

(At least there is no UB in Brainfuck..)

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#186

Earlier quoted context omitted.

I think you missed the part about systems programming. When you are programming real hardware, the focus is entirely on low level details. You need to know the commands being sent to the device, the device state, and the ownership of resources by the device (which Rust doesn't solve for) are correct. The innovation of Rust is the borrow checker, which is primarily of interest to systems programmers. If your primary i…

> there are tools that don't require manual memory management or being pedantic about the different types of strings. You could just use Go, Java, Haskell, Python, etc. 1. Rust doesn't force you to do manual memory management. Rust memory management is automatic by default and only if you really, really want to, you can do it manually. 2. Memory is not the only resource. The GCs in languages you listed only solve the…

1. Rust does manual memory management. It has some syntactic sugar for it in the form of a compiler-enforced RAII, but that is still manual memory management for all practical purposes. A good distinction to make is whether low-level, memory/ownership details leak into public APIs. This is trivially true for Rust, while is not true of managed languages.

3. Rust only addresses problems related to data races, not as an example. All the other race conditions are still on the table. It is a good thing to have, but I think they are the least problematic, and easiest to solve part of concurrency issues.

4. All of these have been known for like 3 decades. There are plenty of managed languages with these, ML, OCaml, Haskell, Scala. But I think your claim is subjective at best.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#187
post #186

Earlier quoted context omitted.

> there are tools that don't require manual memory management or being pedantic about the different types of strings. You could just use Go, Java, Haskell, Python, etc. 1. Rust doesn't force you to do manual memory management. Rust memory management is automatic by default and only if you really, really want to, you can do it manually. 2. Memory is not the only resource. The GCs in languages you listed only solve the…

1. Rust does manual memory management . It has some syntactic sugar for it in the form of a compiler-enforced RAII, but that is still manual memory management for all practical purposes. A good distinction to make is whether low-level, memory/ownership details leak into public APIs. This is trivially true for Rust, while is not true of managed languages. 3. Rust only addresses problems related to data races, not as a…

> It has some syntactic sugar for it in the form of a compiler-enforced RAII, but that is still manual memory management for all practical purposes.

Then you've got a different definition of "manual" than mine. Manual means that developer has to insert calls to allocate / deallocate memory and that the developer is responsible for proving the correctness of those calls. Automated means those calls are done by the runtime or by the compiler automatically, and the compiler makes sure they are correct. In case of Rust, those calls are inserted automatically by the compiler.

> memory/ownership details leak into public APIs

The fact that ownership is a part of public API is a good thing, similarly how it is a good thing to specify an argument is an integer and not a string.

> There are plenty of managed languages with these, ML, OCaml, Haskell, Scala.

I referred to the ones mentioned in the above comment, which mentuoned Java/Go/Python. Haskell/Scala/Ocaml/ML are quite niche even compared to Rust these days.

But even though Haskell / Scala might get close on some type-system features, they don't offer similar experience as Rust in other areas. Haskell is more restrictive in terms of managing state than borrow-checker, and Scala tooling / compile times has been always horrible.

> Rust only addresses problems related to data races, not as an example. All the other race conditions are still on the table.

This is like saying a statically typed language doesn't stop you from putting a string telephone number into a string surname field. Sure it doesn't. But despite that, the value of static types is hard to overestimate.

In practice, the borrow checking + RAII + Send/Sync rules can be used to make the other types of concurrency problems very unlikely by properly modeling the APIs. Sure, no language can protect from all concurrency problems in general, but at least Rust gives you some good tools. For instance it is trivial to forbid concurrent access to something that shouldn't be accessed concurrently and let the compiler enforce that. Now try enforcing that in your "business oriented language of choice". In my experience the majority of concurrency related problems in real large-scale software development happen when some code not designed to handle concurrency accidentally becomes executed concurrently because developers don't realize something is shared and mutated at the same time. Another type of common issue is with communicating concurrent threads of execution, when one sends a message but the receiver is not there on the other end because of premature exit e.g. due to error, leading to a deadlock. Rust protects from those really well.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#188
post #184

Earlier quoted context omitted.

> While you are technically right, one area where the two are unlike is that you want to be polymorph with regards to async/non-async, while it is less often the case for error handling. The reason why we don't want to be polymorphic between fallible and “infallible” functions is that we put a clear social hierarchy between “properly handle error cases” and “panicking”. Using panics instead of `Result` make error han…

Let’s not make this discussion so rust-specific — panics are not used that way in rust for a reason. But exceptions (especially checked exceptions like in java) don’t have that problem, and are exact analogues to Result types. The point is, some way or another that parse function can fail and you may want to handle it. The caller can easily decide that from afar. This is not true of async/blocking — there can be sema…

> Let’s not make this discussion so rust-specific

But this is a discussion about Rust! And my entire point is that async/await is entirely consistent with Rust's overall design.

> But exceptions (especially checked exceptions like in java) don’t have that problem, and are exact analogues to Result types.

Unchecked exceptions don't have this problem (but checked exceptions do), and that's exactly my point. Async/await vs green-thread is exactly the same trade-off than Result vs exceptions: one is “simpler to use”, the other is “simpler to read”. After years of programming, I personally came to the conclusion that we spend more time reading code than writing it (and it's going to be even more true in the near future with LLMs) so I lean on the Result/await side of things, but I don't have fundamental objections against green thread and exceptions.

I do have a fundamental objection against the idea that “async” is somewhat special.

> This is not true of async/blocking — there can be semantic differences between two, otherwise equivalent implementations

Result vs exceptions have also a significant semantic difference: unwinding, and especially the fact that you can trigger unwinding at any point. This is a significant issue when you're dealing with pointers.

> how should an async-block-async call chain work exactly?

I don't really understand this question. An async function is just a regular function that returns a Future, and yes since there's no marker for blocking function you can definitely call one inside an async context, even though it's often a very bad idea from a perf PoV (well it depends, locks are mostly fine, but you need to use them with caution).

In fact, the `async` marker in functions doesn't bring much (again “async function are just regular functions that return a Future”), and it would make much more sense to have a `blocking` stack-contaminating marker on function that call a blocking syscall in order to avoid performance problems due to those, but we can't have nice things because something Path Dependence something…

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#189
post #186

Earlier quoted context omitted.

1. Rust does manual memory management . It has some syntactic sugar for it in the form of a compiler-enforced RAII, but that is still manual memory management for all practical purposes. A good distinction to make is whether low-level, memory/ownership details leak into public APIs. This is trivially true for Rust, while is not true of managed languages. 3. Rust only addresses problems related to data races, not as a…

> It has some syntactic sugar for it in the form of a compiler-enforced RAII, but that is still manual memory management for all practical purposes. Then you've got a different definition of "manual" than mine. Manual means that developer has to insert calls to allocate / deallocate memory and that the developer is responsible for proving the correctness of those calls. Automated means those calls are done by the run…

> The fact that ownership is a part of public API is a good thing

A libraries next version which switches up some internal representations memory handling should ideally not mess up your application, but it also mandates a higher refactor rate when you are only working within your application’s boundaries. These are worthwhile tradeoffs for the niche rust is targeting, but not for every use case.

I’m not saying Rust is a bad language, I really like using it for its intended niche of complex applications where absolute control is needed, like a browser engine. But it is not a panacea and I would definitely not choose it for a CRUD webapp.

Re: Rust fact vs. fiction: 5 Insights from Google's Rust journey in 2022

#190
post #183

Earlier quoted context omitted.

People used to say "when people are forced to use Rust at their job, they'll start hating it, only hobbyists use it and that's why it's so beloved." Do you really consider people learning Rust on the job to be "Rust adopters" who are partisan? Is anyone who ever uses Rust a "Rust adopter" who is unable to give an unbiased opinion? Who would be able to give that opinion, in your view?

> As an engineering manager... > unbiased opinion If the engineering manager after putting so much effort into switching to Rust, and trying to convince upper levels, putting their head at risk and after busting balls for months to make everyone learn Rust, comes into the office one day and asks if we love Rust, we the 77% that want to keep our jobs would answer "OF COURSE WE DO!!!!! COULDN'T BE HAPPIER!!!", with a b…

This hasn't been my experience at all.

Me and all the other developers I know complain endlessly about the tools we're forced to use. We complain to anyone patient enough to listen, including all the engineering managers. No one I know ever got fired or laid off for this.

Post reply on HN