Live data from Hacker News

Rust 1.49.0

blog.rust-lang.org

41–50 of 117 posts

Re: Rust 1.49.0

#41

Earlier quoted context omitted.

Rust has From/Into and TryFrom/TryInto that do the same thing, as far as I can tell. It's not clear to me what the differences are, maybe someone else in this thread will know. :) > Why not hide it a bit by letting the implicit copy to happen to simpler structures ? This is the Copy trait. > Why no love for inheritance There are a variety of reasons, but one interesting one is that inheritance and strong type inferen…

Sorry for got to mention the 'mutable' part. So a mutable singleton variable that has to be marked with an unsafe keyword (and forces the functions that use to be marked as unsafe). The other day I was struggling to implement a singleton (for loading large data from disk) and finally decided to just pass it down the whole chain from the main method. May be I'm missing some easy pz way of doing this ?

So yes, that is because it is unsafe, according to Rust's definition of safety. However, there are tools you can use to remove this.

First of all, I find that many people aren't using multiple threads, and therefore, what they want is a thread-local, not a static. For that, you can use https://doc.rust-lang.org/stable/std/macro.thread_local.html

If you do need a static, then there are libraries like https://docs.rs/lazy_static/1.4.0/lazy_static/ and https://crates.io/crates/once_cell to help too. We have talked about adding something like this to the standard library, but it hasn't landed yet. https://github.com/rust-lang/rust/issues/74465 is the tracking issue for when it does. The reason that we don't have this yet is that it is not super urgent, given that the libraries already exist.

Now, both of those give you immutable statics, but that's where interior mutability comes in. As you can see from the thread_local examples, you can use a RefCell there, and if your type is simple enough, maybe even regular Cell. For lazy_static or once_cell, you may want to use Mutex, or RwLock, or some other type. For simple integers, the various Atomic* types might be better, for example. The reason this isn't built in is exactly because there are so many options; people need all of these specifics, so we have to provide them, so there's no single built-in thing.

Re: Rust 1.49.0

#42
post #40

I recently wrote a utility for myself in Rust after having done several in C#. I like both languages, but Rust introduces pain points for no apparent reason. For example, I hate this way of dealing with errors match result { Ok(value) => value, Err(result) => { panic!("error traversing directories {}", result); } }; It's awkward and ugly. I'm back to C#, now on .NET 5.) and find that it just got noticeably faster! It…

This is pretty nonsensical code so kind of hard to see what your point is.

If the value were being assigned to a variable, it would make tons of sense, IMHO. That it's not means that it's a little useless, but I'm guessing this was typed up for this example, not copy/pasted from real code.

Re: Rust 1.49.0

#43

I recently wrote a utility for myself in Rust after having done several in C#. I like both languages, but Rust introduces pain points for no apparent reason. For example, I hate this way of dealing with errors match result { Ok(value) => value, Err(result) => { panic!("error traversing directories {}", result); } }; It's awkward and ugly. I'm back to C#, now on .NET 5.) and find that it just got noticeably faster! It…

This code is equivalent to result.unwrap_or_else(|e| panic!("error traversing directories {}", e)); There are a lot of methods on various types to reduce this kind of thing. If you didn't want to interpolate the value of e, it would be even simpler: result.expect("error traversing directories");

> If you didn't want to interpolate the value of e

For those reading along (not Steve) expect does do that, but using the Debug formatter instead of Display, as the grandparent used.

Re: Rust 1.49.0

#44
post #22

Earlier quoted context omitted.

It might be worth separating the different improvement areas by section to let people zoom in on what they care about.

We already do that in a pretty granular way, between language, library, compiler, and toolchain features, unless I'm misunderstanding you. Regardless, I don't think the cost/benefit is right here; the posts and notes are already pretty short, and should only take a few minutes to read, even if you read all of them.

aye - the note is very short, I meant that given an index at the beginning one could have more detailed sections that highlight the changes for each section of the language to help avoid "can't please everyone" at the risk of "pleasing no one".

Re: Rust 1.49.0

#45

I recently wrote a utility for myself in Rust after having done several in C#. I like both languages, but Rust introduces pain points for no apparent reason. For example, I hate this way of dealing with errors match result { Ok(value) => value, Err(result) => { panic!("error traversing directories {}", result); } }; It's awkward and ugly. I'm back to C#, now on .NET 5.) and find that it just got noticeably faster! It…

Now try learning about Go's error handling, you will feel better about it :) /s

Jokes aside there are many helper methods on `Result` to make it more Rustic, try looking into: https://doc.rust-lang.org/std/result/enum.Result.html

Re: Rust 1.49.0

#46

Earlier quoted context omitted.

Rust has From/Into and TryFrom/TryInto that do the same thing, as far as I can tell. It's not clear to me what the differences are, maybe someone else in this thread will know. :) > Why not hide it a bit by letting the implicit copy to happen to simpler structures ? This is the Copy trait. > Why no love for inheritance There are a variety of reasons, but one interesting one is that inheritance and strong type inferen…

Sorry for got to mention the 'mutable' part. So a mutable singleton variable that has to be marked with an unsafe keyword (and forces the functions that use to be marked as unsafe). The other day I was struggling to implement a singleton (for loading large data from disk) and finally decided to just pass it down the whole chain from the main method. May be I'm missing some easy pz way of doing this ?

Here's how you can do global mutable state in Rust:

  #[macro_use]
  extern crate lazy_static;

  use std::sync::Mutex;

  lazy_static! {
    static ref ARRAY: Mutex> = Mutex::new(vec![]);
  }

  fn do_a_call() {
    ARRAY.lock().unwrap().push(1);
  }

  fn main() {
    do_a_call();
    do_a_call();
    do_a_call();

    println!("called {}", ARRAY.lock().unwrap().len());
  }
I agree that this isn't the most ergonomic, but like most unergonomic things in Rust, there are reasons for it being so.

Re: Rust 1.49.0

#47
post #23

Earlier quoted context omitted.

Right but as a general rule you'll mostly only be using `s.into()` to get a `String` from an `&str`. Or `&s` to deref `String` to a `&str`. I'm not sure why this would require a crate to handle? The other ways are more "advanced", for when you're dealing with (for example) potentially unsafe coercions or you don't want to rely on inference for some reason.

I agree with you that I'm not sure what your parent is talking about, I'm just here to give all the examples. Deref coercion takes 99% of my String -> &str conversions, and I reborrow for that rare 1%, personally.

Yeah sorry, I'm just really confused about what's being asked for.

Re: Rust 1.49.0

#48

Earlier quoted context omitted.

Sorry for got to mention the 'mutable' part. So a mutable singleton variable that has to be marked with an unsafe keyword (and forces the functions that use to be marked as unsafe). The other day I was struggling to implement a singleton (for loading large data from disk) and finally decided to just pass it down the whole chain from the main method. May be I'm missing some easy pz way of doing this ?

Here's how you can do global mutable state in Rust: #[macro_use] extern crate lazy_static; use std::sync::Mutex; lazy_static! { static ref ARRAY: Mutex > = Mutex::new(vec![]); } fn do_a_call() { ARRAY.lock().unwrap().push(1); } fn main() { do_a_call(); do_a_call(); do_a_call(); println!("called {}", ARRAY.lock().unwrap().len()); } I agree that this isn't the most ergonomic, but like most unergonomic things in Rust, t…

(You'd probably replace the first two lines with "use lazy_static::lazy_static;" in today's Rust, that older style isn't as idiomatic.)

Re: Rust 1.49.0

#49

Earlier quoted context omitted.

In C# there is a helper class: https://docs.microsoft.com/en-us/dotnet/api/system.convert?v... I'm still figuring my way around rust so obviously some noob questions follow: -> what's with the move/copy mess ? I know why they are needed but it seem to be in the face with all the explicit '&' all over the place in any reasonably sized code. Why not hide it a bit by letting the implicit copy to happen to simpler struct…

> Why not hide it a bit by letting the implicit copy to happen to simpler structures. This is already the case. Built-in types that are simple enough to be copied implicitly already are (roughly: those which don't manage any memory or other resources), and you can enable this for your own types with `#[derive(Copy)]`, as long as they are composed only of implicitly copyable types. #[derive(Copy)] struct S { x: i32, y…

The misunderstanding may come down to the fact that strings are "primitives" in many languages - for usability reasons - despite carrying the memory/performance traits of a full, heap-allocated "object". If someone has never worked in a language where strings are not primitives, I can see how they might be irked/confused by suddenly having to deal with that.

Re: Rust 1.49.0

#50

Earlier quoted context omitted.

In C# there is a helper class: https://docs.microsoft.com/en-us/dotnet/api/system.convert?v... I'm still figuring my way around rust so obviously some noob questions follow: -> what's with the move/copy mess ? I know why they are needed but it seem to be in the face with all the explicit '&' all over the place in any reasonably sized code. Why not hide it a bit by letting the implicit copy to happen to simpler struct…

You are essentially complaining that Rust is not C#, while at the same time admitting that you don't know much about the language. Rust is much lower level and makes very different tradeoffs. Sometimes for the sake of performance, sometimes to enhance code readability. But most of the design decisions are there for a reason, and are good choices. Simple types (that are small and can be trivially memcopied) can implem…

Expanding a bit on conversions: C#'s `Convert` conflates several different operations.

Examples:

Convert.ToInt32(String) – This is _parsing_. In Rust, use `parse`.

Convert.ToString(Int32) – This is _stringifying_. In Rust, use `to_string`.

Convert.ToInt64(Int32) – This is an _infallible conversion_. In Rust, use `into`.

Convert.ToInt32(Int64) – This is a _fallible conversion_. In Rust, use `try_into`.

In all these cases, Rust gives you more immediate semantic information about the conversion, and in fewer characters too!

Post reply on HN