Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Speaking of ergonomics, I seem to write a good deal of this for short-circuiting in Rust:

    let x = match x {
      Some(x) => x,
      None => return None,
    }
Rust doesn't have any other way to short-circuit and it gets pretty tedious.

I think Kotlin's named returns are most ergonomic of all. That way you can just short-circuit from anywhere whether in the middle of a fold or a deeply nested iteration.

    fn foo() {
      for x in xs {
        for y in ys {
          if y == 42 {
            return@foo 42
          }
        }
      }
    }
The other thing I'd like for other languages to steal for Kotlin is how everything has the .let/.apply/etc. methods.

I'm rusty so this is more pseudocode, but these methods basically let you bring your own chaining to any value.

    let y = x.let { x ->
        x + 100
    }.apply { x ->
        println(x)
    }.let { x -> 
        x * 2
    }
Once you use it, it feels pretty silly that library authors in other languages have to deliberately design a chainable API for the same ergonomics. ...And infuriating when you want to chain some more in other languages but you've run out of chain context.

Like when you use `.unwrap_or()` in Rust but still want to continue chaining on to the value. But can't because it's not in a container anymore with a chainable API.

    let x = maybe
        .map(foo)
        .and_then(bar)
        .unwrap_or(42);
        // ugh, want to apply a function to the result so
        // far but can't use `.map(to_base16)` because 
        // it's been unwrapped into u32.
Just some things from my wishlist for the next language someone makes.


Rust has ? for early returns when returning an Option, and it has named breaks as well.

    fn foo(xs: Vec<u32>, ys: Vec<u32>) {
      'bar: for x in &xs {
        for y in &ys {
          if *y == 42 {
            break 'bar;
          }
        }
      }
    }


  let x = match x {
      Some(x) => x,
      None => return None,
  }
This implies your function returns an `Option`, and that `x` is an `Option` too. In which case you can just do

  let x = x?;


Well, you may be short-circuiting for any reason, from any signature.

For example, look a Swift's guard statements. It even narrows the type down-scope after you short-circuit.

If you borrow in the `match {expr}`, Rust still thinks it matters when you're trying to short-circuit in the `None` branch and will complain about the borrowed lifetime. Though this is something #![feature(nll)] fixes.

You can implement std::ops::Try for a custom data structure, but that doesn't help you in any of the cases where you just want to do some day-to-day short-circuiting without inventing your own data structure.

I shouldn't have used Option, though. It was a bad example.


I used it frequently when mixing `Result` with `Future`. For example,

  fn do_something() -> Box<Future<Item=(), Error=Error>> {
    let val = match do_result() {
      Ok(x) => x,
      Err(e) => return Box::new(err(e.into())),
    };
    // do something with `val`
    unimplemented!();
  }


If you want to cut down on lines, this is equivalent:

    let val = do_result().map_err(|e| Box::new(err(e.into())))?;


I often miss Ruby's 'tap' when writing Java. Happily, in Rust, it's easy enough to add yourself:

https://play.rust-lang.org/?gist=d40d8ca9bd77bbd60626be72740...

I only implement let and also from Kotlin, because Rust doesn't really have the idea of method receivers in quite the same way as Kotlin, so the others are pointless.


For this example of yours:

    let y = x.let { x ->
        x + 100
    }.apply { x ->
        println(x)
    }.let { x -> 
        x * 2
    }
I think you've just reinvented imperative control flow. Isn't your example just modeling a reusable function that represents a series of instructions on a value?

    func(x) {
      let y = x + 100
      println(y)
      let z = y * 2
      return z
    }


A bunch of languages have something much like .let/.apply already, since it's pretty much just function application in reverse order:

    "foo" |> String.length |-> printf "%d\n" |> fun x -> x + 100




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

Search: