These are chat archives for rust-lang/rust

7th
May 2017
Michael Thomas
@Michaelt293
May 07 2017 01:06

I'm stuck on a problem at the moment.

struct Isotope {
    nucleons: Nucleons,
    isotopic_mass: IsotopicMass,
    isotopic_abundance: IsotopicAbundance,
}

struct Element {
    atomic_number: AtomicNumber,
    element_name: ElementName,
    isotopes: Vec<Isotope>,
}

fn element_most_abundant_isotope(e: Element) -> Isotope {
    e.isotopes
        .iter()
        .max_by(|a, b| a.isotopic_abundance.partial_cmp(&b.isotopic_abundance))
        .unwrap()
}

IsotopicAbundance is a type alias for f64. The function element_most_abundant_isotope doesn't compile. Any ideas why?

Sherzod Mutalov
@shmutalov
May 07 2017 01:08
Can you paste error log?
Michael Thomas
@Michaelt293
May 07 2017 01:13
 Compiling neutron v0.1.0 (file:///Users/michaelthomas/src/neutron)
error[E0308]: mismatched types
   --> src/base.rs:178:24
    |
178 |         .max_by(|a, b| a.isotopic_abundance.partial_cmp(&b.isotopic_abundance))
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::cmp::Ordering`, found enum `std::option::Option`
    |
    = note: expected type `std::cmp::Ordering`
               found type `std::option::Option<std::cmp::Ordering>`
    = help: here are some functions which might fulfill your needs:
            - .unwrap()

error[E0308]: mismatched types
   --> src/base.rs:176:5
    |
176 |       e.isotopes
    |  _____^ starting here...
177 | |         .iter()
178 | |         .max_by(|a, b| a.isotopic_abundance.partial_cmp(&b.isotopic_abundance))
179 | |         .unwrap()
    | |_________________^ ...ending here: expected struct `base::Isotope`, found reference
    |
    = note: expected type `base::Isotope`
               found type `&base::Isotope`

error: aborting due to 2 previous errors

error: Could not compile `neutron`.
I have written very little rust code so I'm having a bit of trouble following what's going on
Sherzod Mutalov
@shmutalov
May 07 2017 01:16
You need to add some changes
fn element_most_abundant_isotope(e: Element) -> &Isotope {
    e.isotopes
        .iter()
        .max_by(|a, b| a.isotopic_abundance.partial_cmp(&b.isotopic_abundance).unwrap_or(false))
        .unwrap()
}
Try, but remember,I am newbie too )
Michael Thomas
@Michaelt293
May 07 2017 01:21

thanks for your help

  Compiling neutron v0.1.0 (file:///Users/michaelthomas/src/neutron)
error[E0106]: missing lifetime specifier
   --> src/base.rs:175:49
    |
175 | fn element_most_abundant_isotope(e: Element) -> &Isotope {
    |                                                 ^ expected lifetime parameter
    |
    = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
    = help: consider giving it an explicit bounded or 'static lifetime

error: aborting due to previous error

error: Could not compile `neutron`.

this is getting confusing very quickly for my newbie brain :)

Sherzod Mutalov
@shmutalov
May 07 2017 01:24
fn element_most_abundant_isotope<'a>(e: &Element) -> &'a Isotope {
    e.isotopes
        .iter()
        .max_by(|a, b| a.isotopic_abundance.partial_cmp(&b.isotopic_abundance).unwrap_or(None))
        .unwrap()
}
I am not familar with lifetimes too :P
Michael Thomas
@Michaelt293
May 07 2017 01:26
thanks again for your help, it seems like I need to do some more reading
borrowing, references and lifetimes are ideas that I haven't got my head around yet
Sherzod Mutalov
@shmutalov
May 07 2017 01:28
Also, note that, your program will fail, if you call element_most_abundant_isotope with Element e which doesnt contain any comparable isotopic_abundance (what is that??? LOL)
Suggestion, return Option<Isotope>, not Isotope
Michael Thomas
@Michaelt293
May 07 2017 01:31
Thanks for the suggestion. That is true, if an element doesn't have any stable isotopes, you'd end up with a empty vector.
Jonas Platte
@jplatte
May 07 2017 01:31
@Michaelt293 If you are not already reading that, have a look at the second edition of the rust book. It's not finished yet, but most of the chapters have been written and the earlier stuff has also been reviewed and all.
Sherzod Mutalov
@shmutalov
May 07 2017 01:32
@Michaelt293 I love science, your program seems to me very interesting, but I am just freak :(
Jonas Platte
@jplatte
May 07 2017 01:32
the lifetime and borrowing explanations from the first edition are something many people complain about and IMO the second edition does a much better job explaining them
Michael Thomas
@Michaelt293
May 07 2017 01:33
@jplatte will do. I did read through the first version quite a while ago and have started reading through the second version this weekend.
Jonas Platte
@jplatte
May 07 2017 01:34
@Michaelt293 Also, in the program above, is Isotope actually just an alias for a primitive numeric type?
Sherzod Mutalov
@shmutalov
May 07 2017 01:35
@jplatte
struct Isotope {
    nucleons: Nucleons,
    isotopic_mass: IsotopicMass,
    isotopic_abundance: IsotopicAbundance,
}
Jonas Platte
@jplatte
May 07 2017 01:36
Oh, should have read more carefully
Right, and max_by works for any type.
Michael Thomas
@Michaelt293
May 07 2017 01:38
I have written a library in haskell - https://hackage.haskell.org/package/isotope - porting this library to rust has been on my to do list for a while
Jonas Platte
@jplatte
May 07 2017 01:40
Okay, so do you still want an explanation of what's going wrong in your particular example, or do you want to get back to the book first?
Because I think I should be able to help you in the former case.
Jonas Platte
@jplatte
May 07 2017 01:54
Well I really have to go to bed, but here is a minimal compiling version (well, not really since there is no main, but there are no more other compiler errors): https://is.gd/sHFEfV
I didn't write anything about the lifetime stuff, because I'll never explain that better than the second edition book, but I did write a small comment about the point of the unwrap_or that @shmutalov added when he first tried to make this function work.
Sherzod Mutalov
@shmutalov
May 07 2017 01:56
@jplatte if one of values is NaN, I think None will good result for partial_cmp
Jonas Platte
@jplatte
May 07 2017 01:57
@Michaelt293 In any case: Good luck with your port :)
@shmutalov Uhm, yes that's why it's implemented like that... not sure what you're saying here.
anyway, I'm going to bed now. I'll be back tomorrow
Sherzod Mutalov
@shmutalov
May 07 2017 01:59
@jplatte partial_cmp returns Option<Ordering>, so we can return Ordering:XXX or None,right? None seems best choice for comparing "unknown" values
@jplatte :+1:
@jplatte OMG, I am totaly wrong here.I am sorry :D
Jonas Platte
@jplatte
May 07 2017 02:02
@shmutalov Yes, that's what partial_cmp returns. And then you call unwrap_or because max_by expects a function that returns an Ordering, not Option<Ordering>.
Sherzod Mutalov
@shmutalov
May 07 2017 02:02
@jplatte yes, I must read carefully,sorry for that
Masaki Hara
@qnighy
May 07 2017 02:43
Hello! I have a question. In the code here https://is.gd/QDyn4D , is the function with safe? If so, is there any equivalent in std or other crates?
Masaki Hara
@qnighy
May 07 2017 02:49
fn with<T, F: FnOnce(T) -> T>(this: &mut T, f: F) {
    unsafe {
        std::ptr::write(this, f(std::ptr::read(this)));
    }
}
Michael Thomas
@Michaelt293
May 07 2017 04:11
@jplatte awesome, thanks a lot.
red75prime
@red75prime
May 07 2017 04:32
@qnighy No. It is not safe. It can cause double free if f panics. https://play.rust-lang.org/?gist=ebfd6e13fac57da9cb819033004889d2&version=stable&backtrace=0
Masaki Hara
@qnighy
May 07 2017 04:36
@red75prime I completely forgot about unwinding. Thank you.
Michael Thomas
@Michaelt293
May 07 2017 11:33
Is there a library that you recommend for a Monoid trait?
Jonas Platte
@jplatte
May 07 2017 11:42
@Michaelt293 Depending on why you want it, you could either use frunk, which isn't very widely-used AFAIK; or just do the easy thing and use Default + Add (both are in std) over a proper Monoid trait (because I don't think there ever really is a practical difference)
Michael Thomas
@Michaelt293
May 07 2017 11:45
Great.....I might just go with the easy way for now. One question, before you used the newtype pattern https://aturon.github.io/features/types/newtype.html - if I simply want to unwrap the newtype and get the value, what is the best way?
I found https://rust-bio.github.io/rust-bio/newtype_derive/index.html but it doesn't seem too widely used
Jonas Platte
@jplatte
May 07 2017 11:46
well newtypes in Rust really are tuple structs, and tuple structs have numerical members (as in x.0, x.1, ...)
So you can extract the content of a newtype with .0
Or you can just use an irrefutable pattern, e.g. let NewtypeName(content) = newtype_value;
The same actually works in fn definitions: fn foo(NewtypeName(content): NewtypeName) -> NewtypeName { ... }
Which would be like the following Haskell code:
foo :: NewtypeName -> NewtypeName
foo (NewtypeName content) = ...
Michael Thomas
@Michaelt293
May 07 2017 11:52
thanks, forgot that about .0....does the job. I was thinking I had to use pattern matching