Follow

No joke I totally love for its match syntax.

Checking for three environment variables, returning the first match and returning a standard if none matched:

Well we can even get rid of the variables and just do

return match ...

@Nervengift true! I always forget about removing `return` and final `;` in Rust :D

@kevin if you want a more functional approach, you can also write it like this:

(And if you're okay with eager evaluation, you can even skip the closures by using .or(..) and .unwrap_or(..) )

@zatnosk thanks! Others recommended this, too. I didn't know about .or() before! :)

@kevin for the sake of showing the match syntax, this is valid... but just so you know, it is possible to write that same thing in way less code: play.rust-lang.org/?version=st

@musicmatze oh wow! This is really nice, too! Didn't know about or_else()!

@kevin as @musicmatze already mentioned there are easier ways to do this. Especially for Option and Result there are tons of helper functions that can help to reduce the amount of nesting.

I check the rust docs of option and result quite often. Recently had my first case where I could use transmute.

@dnaka91 @musicmatze don't know about transmute yet but I'm having a really bad time unwrapping nested AWS API responses right now.

Will look into it!

@dnaka91 @musicmatze This is the "oh it finally works but please don't break" unwrap I have now :D

@kevin @dnaka91 looks a lot like you want to use the "?" operator alongside with some `Option::ok_or_else()` to actually handle errors.

@kevin @musicmatze if you wanna got really safe, you should also switch the indexed accesses like something[0] with get, like something.get(0).

For handling expected values in Option I find the Context extension of the anyhow crate really helpful too. It turns your Option into a result with the provided string as error.

Like:
let x = opt_value.context("value missing")?;

Especially helpful in chained calls.

@kevin @dnaka91 if your functions return `Result` themselves, use the `?` operator!

@kevin have you seen this:
use std::env::var;
var("USER").or(var("HOME")).or(var("HOSTNAME")).or(String::from("no var matched"))
imo a little cleaner and shorter. you can use or_else if evaluating lazy matters to you

@kevin note the lack of return and semicolon, all blocks are expressions with the value of the last expression, including function definitions

@cosine haven't seen this!

Using .or looks a lot cleaner and is easier to understand!

@kevin yay. there all sorts of functional methods for most of the wrapper classes like and, map, as_ref

@cosine I'm fairly new to rust and I keep learning new awesome stuff!

Will check them out next time I need it. :)

@veer66 I think you can, my VSCode plugin runs formatting on save so that's why I have all the indents.

@kevin I meaned an alternative syntax, which doesn't have to use embedding { }.

@kevin I love pattern matching in Haskell too!

There you can combine it with something resembling function overloading...

@kevin C isn’t that different though (and more compact in this case), something like this should work fine:

char *user; if(NULL == (user = getenv("USER"))) { if(NULL == (user = getenv("HOME"))) { if(NULL == (user = getenv("HOSTNAME"))) { user = "no var matched"; } } } return user;

Only kind where it’s quite different is stuff like Elixir, which I’m linking because this particular example would be less pretty because of the mutable nature of environment variables: https://elixir-lang.org/getting-started/case-cond-and-if.html

@kevin :blobdizzy: :antifa: @Adrian Cochrane The same is expressed more succinctly like this:

fn get_user_id_from_env() -> String {
std::env::var("USER")
.or_else(|_| std::env::var("HOME"))
.or_else(|_| std::env::var("HOSTNAME"))
.unwrap_or(String::from("no var matching"))
}


No pattern matching this way, though.

@kevin You can reduce the indentation level using tuples:

let user = match (std::env::var("USER"), std::env::var("HOME"), std::env::var("HOSTNAME")) {
(Ok(h), _, _) => h,
(Err(_), Ok(h), _) => h,
(Err(_), Err(_), Ok(h) => h,
(_, _, _) => String::from("no var matched"),
};

(Also, use std::env::var could make it easier to read.)

@kevin I'm not a fan of that deep nesting though. Especially because AFAICS, you can test for all the matches on the same level. There could be just one Err, not?

Sign in to participate in the conversation
Mastodon

bullgit.party is a instance for everyone who is part of bullgit. 🎉