These are chat archives for rust-lang/rust

16th
Feb 2019
Wil Hunt
@huntwj
Feb 16 00:04

Ok, so I have the following code, and it works. My question, is there a cleaner more “rusty” way of doing this without a mut variable?

use rocket::http::Status;
.
.
.
    // error_code: Option<u16>
    let mut status = Status::InternalServerError;
    if let Some(error_code) = error_code {
        if let Some(valid_status) = Status::from_code(error_code) {
            status = valid_status;
        }
    }
    builder.status(status);

In case it’s not clear, I want to use Status::InternalServerError for all cases except when error_code is present and translates into a valid Status. Again, this code works, but it feels like I’m missing an easier way to express it.

Ichoran
@Ichoran
Feb 16 00:17
I would tend to
let status = error_code
    .and_then(|e| Status::from_code(e))
    .unwrap_or(Status::InternalServerError);
Can probably just and_then(Status::from_code) (without the |e| and (e))
Note that if you are doing something expensive to create the default value you should use unwrap_or_else to generate it when needed. Here it's just a value, I imagine, so it should be fine.
Wil Hunt
@huntwj
Feb 16 00:58
Ty. I’ll work on parsing that internally here in the next few minutes.
Ichoran
@Ichoran
Feb 16 01:12

You could also avoid the mut by repeating yourself with

let status =
    if let Some(ec) = error_code {
        if let Some(valid_status) = Status::from_code(ec) { valid_status }
        else { Status::InternalServerError }
    }
    else { Status::InternalServerError }

but I think using the functions on Option are more compact and better convey (to those who know them) what you mean. You're doing something pretty common, and Option has functions that define a compact language for talking about (and doing) that kind of thing.

Wil Hunt
@huntwj
Feb 16 01:31

Yes. I do like your code better now that I’ve re-read about those functions. Are they generally preferable to match blocks, for most rustations? For example, when using std::result::Result we have two ways of mapping our answers out:

// my_result: std::result::Result<String, u32>
let output = match my_result {
    Ok(value) => map_success_string(value),
    Err(code) => map_error_code(code),
}

or you could use those functions:

let output = myself.map(|value| map_sucess_string(value))
    .unwrap_or_else(|code| map_error_code(code));

The first, while longer and more wordy, is probably clearer, especially for people newer to Rust. But am I right in guessing the second is the more preferred way in the general case?

Sean Perry
@shaleh
Feb 16 05:54

How can I implement this generic function?

pub fn example(value: T) -> bool {
value < 256
}

I cannot find a good way to say "PartialOrd and a Number". It has something to do with 256 not having a n explicit
type I think.

Zakarum
@omni-viral
Feb 16 06:23
pub fn example<T: PartialOrd<u16>>(value: T) -> bool {
  value < 256u16
}
Vitaly
@Virtuos86
Feb 16 06:31

@omni-viral

pub fn example<T: PartialOrd<u8>>(_value: T) -> bool {
    true
}

:-)

Zakarum
@omni-viral
Feb 16 06:32
:+1:
Actually I think this one better
pub fn example<T: Into<u64>>(value: T) -> bool {
    value.into() < 256u64
}
Vitaly
@Virtuos86
Feb 16 06:39
I think we need a little more detail.
Sean Perry
@shaleh
Feb 16 06:55
I have a couple of types floating around. I wanted the generic function to avoid kinda useless casting in a few spots.
usize as isize, that kinda thing.
That last one is likely the best version, yeah.
Zakarum
@omni-viral
Feb 16 10:00
Unfortunatelly usize doesn't implement Into<u64>
To safely cast usize to uN you should use cfg(target_pointer_width = X)
You can actually assume usize is always fit into u64 but that will make your code not future-proof
tsoernes
@tsoernes
Feb 16 10:06
Given that I have an Arc<String> can I produce a slice of that string, i.e Arc<&str>?
I want to achieve something like this (which does not compile):
    let s: Arc<String> = Arc::new("hello".to_owned());
    for i in 0..s.len() {
        let slice = Arc::clone(&s[i..i + 1]);
        thread::spawn(move || {
            println!("{}", slice);
        });
    }
Zakarum
@omni-viral
Feb 16 11:57
You can make it Arc<str>
But then you would need some magic to make parts of the str into Arcs
Michal 'vorner' Vaner
@vorner
Feb 16 14:53
I think you can't share the reference count, therefore it won't work.
Zakarum
@omni-viral
Feb 16 15:57
Yeah, @vorner is probably right, because Arc contains single pointer to refcount followed by data
raja sekar
@rajasekarv
Feb 16 17:20
Guys what is your opinion of this crate https://github.com/alecmocatta/serde_closure ? Is it a good idea to use this to build distributed computation libraries in Rust?
tsoernes
@tsoernes
Feb 16 17:24
is there a way to partially consume an iterator, then consume the rest later on? Something like this:
let x = vec![1,2,3].into_iter();
for y in x.take(2) { // 1, 2 }
for y in x { // 3 }
John
@onFireForGod_gitlab
Feb 16 21:18
error[E0716]: temporary value dropped while borrowed
  --> src/middleware/user_roles.rs:13:31
   |
13 |         let auth_info = match req.extensions().get::<Auth>() {
   |                               ^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
why does this happen?
Do I really need to make a seperate variable for each chained function?
matrixbot
@matrixbot
Feb 16 21:21
bspeice Can you post a larger sample? Or something on Rust playground to make sure? This typically happens because get fetches something from inside an object that gets dropped once the call ends; the inner Auth would then outlive what extensions() returned.
Ichoran
@Ichoran
Feb 16 21:21
@tsoernes - It works if you step through manually; in general, no, you can't (unless you clone it).
tsoernes
@tsoernes
Feb 16 21:21
i see. thanks
Ichoran
@Ichoran
Feb 16 21:22
You can try itertools also to see if there's a function/struct that does what you want.
It doesn't solve the problem in general, but there are various specific ways to chunk and otherwise manipulate iterators.