Hacker News new | past | comments | ask | show | jobs | submit login

For me, a feature I'd really hope for is the elusive "if not let" (or however this gets named eventually), to let me escape the currently unavoidable clutches of Rust's rightwards drift and accruing mental context.



Swift has had ‘guard’ statements since 2015, and it’s the biggest thing I miss when programming in Rust:

    guard let x = ... else {
        // must not fall through, so a return, break, throw, non-returning function call, etc. is required
    }
    // do something with x


In Rust I would just do:

    let x = match foo {
        Some(x) => ...,
        None => return // or break, etc.
    };
    // do something with x
(This is assuming that you don't want to propagate an error or panic, which could be more easily done with `foo?` or `foo.unwrap()` respectively.)


A nice quality of the `guard` in swift is that you can chain multiple conditions, which is harder to do in rust (maybe with some macros a la if_chain?)


I ran into this the other day, and it took me a moment to realise that I could just use `matches!`:

    // want to do this
    if not let Some("pattern") = val {
        doSomething();
    }

    // can instead do
    if !matches!(val, Some("pattern")) {
        doSomething();
    }


That won’t allow extracting a value from the optional though, will it? i.e. I can’t do this something along the lines of:

    if !matches!(val, Some(let x))


Indeed not, so it's not a full replacement. I'm not entirely sure that I like the idea of an "if let" variant creating bindings that escape the visual block, but I'd probably get over it.


Lol it would be kinda funny to have this:

    let input: Option<usize> = Some(1);
    if let Some(value) != input {
        return 0;
    }
    // use value; such that value: usize = 1


We already have something close:

  let input: Option<usize> = Some(1);
  let value = match input {
    Some(x) => x,
    _ => return 0,
  };
  // use value; such that value: usize = 1


That works, but it's clunky enough that it defeats the purpose of writing guard statements IMO. It's not hard to understand, but it's also not possible to figure out what it means at-a-glance. I have to stare at it for a few seconds to try to figure out where all control flow is going to go -- it has two levels of nested subexpressions, along with branches that appear similar but do very different things (returning a value from the expression vs. from the function).

The point of a 'guard' clause is to visually distinguish between the "expected" and "unexpected" case. When I see a guard statement:

    let input: Option<usize> = Some(1);
    guard let Some(value) = input else {
        return 0;
    }
    // use value; such that value: usize = 1
I immediately know that the rest of the function expects input to contain a value, and that whatever is after the 'else' is some kind of error handler. Your match statement might have the same effect functionally, but visually it's confusing because it's not immediately obvious which branch is the happy-path. I'd rather read a function containing ten guard clauses than a function containing ten of those matches.


Some(1).unwrap_or(0)


Return 0 is different from using 0 in the rest of the function body.


Rust has this, it's `let ... = match { ... };`.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: