Live data from Hacker News

100 days with Rust: a series of brick walls

brandur.org

201–210 of 323 posts

Re: 100 days with Rust: a series of brick walls

#201
post #110

Earlier quoted context omitted.

> My code was littered with .as_str() and .to_string(). PSA: If you have a variable that's a String, you can easily pass it to anything that expects a &str just by taking a reference to it: fn i_take_a_str(x: &str) {} let i_am_a_string = "foo".to_string(); i_take_a_str(&i_am_a_string); Every variable of type &str is just a reference to a string whose memory lives somewhere else. In the case of string literals, that m…

Ah, I found that out later but had forgotten all about it. :) I don't remember how I found out, but it seemed oddly magical until I just now read the docs: String implements Deref . Makes more sense now. I still had a bunch of to_strings()'s, though, as things tended to take String whenever I had &str's. I found this to be a very unexpected nuisance. EDIT: Maybe I needed as_str() as the & trick doesn't work if the ta…

It's relatively rare that APIs should be taking ownership of `String`s from you; the majority of the time arguments should be borrowed. I'm curious what cases you ran into most frequently that required `String`.

Re: 100 days with Rust: a series of brick walls

#202

Earlier quoted context omitted.

"Don't use heap memory after it's been freed" is C++ (and C) 101 as well. Yet if the bar for C++ competence is "never wrote a use-after-free", then your bar for "competence" excludes essentially everyone in the industry. Whether a theoretically "competent" C++ developer makes mistakes related to object slicing is a completely uninteresting debate. Whether experienced C++ programmers make that mistake in practice is t…

> Yet if the bar for C++ competence is "never wrote a use-after-free" The bar for C++ competence in that regard is RAII. Furthermore, your strawman doesn't hold up. The object slicing problem is actually like someone being foolish enough to cast a 64-bit int to a 32-bit int and then complaining that the programming language is broken because the 32-bit variable doesn't hold 64 bits. Of course it doesn't. Why should i…

Actually no.

RAII only works for stack or static global allocated resources.

So if the heap allocated data isn't hidden behind some kind of smart pointer, RAII won't help.

Which unless one writes 100% of the code, or there are strict code reviews in place, there isn't any guarantee that all heap allocations are guarded with RAII based handles.

Re: 100 days with Rust: a series of brick walls

#203
post #71

Earlier quoted context omitted.

I recently wrote a few projects in Rust (C/C++/Go/JavaScript/Java/Python as background), and very much like the language. My 2 cents from my endeavors with Rust I felt like all type errors are backwards. That is, "got" was the target you are giving your type to, not the type that you are passing. This may only happen in some cases, but I just started tuning the content of those errors out and instead adjusted randoml…

> Enums are super nice, but it's very annoying that you cannot just use the value as a type. My project had a lot of enums (user-provided query trees), and it was causing a lot of friction. Note that OCaml has this feature of using-a-enum-value-as-a-type (or using a subset of enum values as a type, etc.). It works very well, but it quickly produces impossibly complicated error messages. I'd like Rust to have this fea…

I am not very familiar with OCaml, but why would such a feature result in complicated error messages? I can only really imagine two new error scenarios: "Expected Enum::ValueA, got Enum" and "Expected Enum::ValueA, got Enum::ValueB".

Re: 100 days with Rust: a series of brick walls

#204
post #120

Disclaimer: Am a C++ programmer Watching from a distance I have to concede that from a safety, dynamism of the community and package management using cargo Rust has improved upon C++ in meaningful and measurable way. However on the complexity of the language front, I wonder if Rust will also join C++ in the realms of "too complex" 10 years from now. Would love to get some Rust experts to weigh in here on their though…

Rust is certainly not the "end of history" for programming languages. But, taking on that task is for future generations of language devs; it's an open research question today. I can only hope so!

I wrote some thoughts about "complexity" and language design here: http://words.steveklabnik.com/the-language-strangeness-budge...

I also think the difference between incidental and inherent complexity is important...

Re: 100 days with Rust: a series of brick walls

#205

Earlier quoted context omitted.

Oh, and added thing that bugged me a lot: The error part of Result . During my short time of coding Rust (I'll get back to it later), I never really found a way to ergonomically handle errors. I find it really awkward that the error is a concrete type, making it so that you must convert all errors to "rethrow". Go's error interface, and even exception inheritance seems to have lower friction than this.

? should help a lot with this, but libraries like error-chain, or the newer (and, IMO much better) failure can help even more.

But ? only worked if the function it was used in had the same error type as the function you called, which was mostly not the case...

... I think. I don't remember it that vividly.

Re: 100 days with Rust: a series of brick walls

#206
post #156

Earlier quoted context omitted.

> Ah, it sounds like you're using traits as types directly, which is very much discouraged by Rust (especially in conjunction with taking references to those traits). What the language really prefers for you to do is to use traits as bounds on generic types Can you write an example?

Sure thing. [Preemptive postscript: damn this got long. TL;DR don't use trait objects, just use generics. You'll thank me.] Here's the setup: we have several different types, and those types implement the same trait (think of it like an interface from other languages). // Define two different types struct Chihuahua; struct GreatDane; // Define a trait with a method trait Bark { fn bark(&self); } // Implement that met…

(Minor point:

> Not only do you have to box it up manually, but you have to cast it into a trait object

There's an implicit coercion from Box to Box if T impls Trait, if it's 'obvious' that such a coercion is required, such as passing a Box as an argument with type Box.)

Re: 100 days with Rust: a series of brick walls

#207

PG had this comment about programming languages: The correct solution of a problem is the most simple solution. Just like in math, you can solve one problem in multiple ways, but the correct one is the shortest, beautiful looking one. When I look at Rust, it gives the feeling "could be simplified". Obviously it's a new language and it comes with lots of cool stuff, but it looks ugly, doesn't excite those who seek sim…

There are some ways in which Rust can be simpler; see my above comments about learn ability. But a lot of the complexity is inherent in the choices we've made for the constraints of the language. For example, including a GC would make things much simpler in some ways! But it would also make it not appropriate for many of the use cases that are crucial to Rust's existence.

Re: 100 days with Rust: a series of brick walls

#208

Author here. I want to apologize a bit for the tone of this article — it was written from a place of frustration, and this part of the site is very much akin to a development journal — these are short articles without a lot of concrete facts that are not really intended for broad or comprehensive consumption. In no way is this meant to be an anywhere-near comprehensive critique on Rust. I'll quickly point out that Ru…

No worries There's a lot of stuff coming down the pipeline that I think would help you a lot.

> there's a distinct lack of pragmatism around getting core features like concurrency nailed down and shipped.

For one example; we're working really hard right now on getting async/await shipped, and dealing with ergonomics problems around it. The recent changes are to make it simpler, not make it harder. For example, you should need to think a lot less about future composition, since you'll be able to borrow across futures, as just one example.

There might be a disconnect between what we're working on and what we're perceived to be working on. Messaging is hard!

You're 100% right that criticism is the only way to evolve, and so I appreciate calling out things that aren't great. Details help, but as you said, this blog post wasn't intended for this audience, which is a problem I feel quite deeply, personally. So I get it :)

Re: 100 days with Rust: a series of brick walls

#209

Earlier quoted context omitted.

? should help a lot with this, but libraries like error-chain, or the newer (and, IMO much better) failure can help even more.

But ? only worked if the function it was used in had the same error type as the function you called, which was mostly not the case... ... I think. I don't remember it that vividly.

It doesn't have to be the same type, there just has to be a suitable implementation of the 'From' trait to perform the conversion if the types don't match.

Re: 100 days with Rust: a series of brick walls

#210

Earlier quoted context omitted.

? should help a lot with this, but libraries like error-chain, or the newer (and, IMO much better) failure can help even more.

But ? only worked if the function it was used in had the same error type as the function you called, which was mostly not the case... ... I think. I don't remember it that vividly.

? calls a conversion function. It only won't work if the error you're trying to return won't convert to the error that's in the type signature. Even then, you have options, like .map_err.
Post reply on HN