Hacker News new | ask | show | jobs
by falcolas 4155 days ago
My experience mirrors the author's: it results in a lot of use of macros and case statements. These create a fair bit of cognitive overhead to discern what the program flow will end up being, and special syntax for unpacking values.

The broad use of case statements leads to one more odd problem - knowing when, and when not, to use a `;`. Explicit returns are frowned upon, they prefer the "results from the last expression" form of returns. The `;` results in an expression returning a different value and a different type. The type system will usually catch these errors and print a helpful "perhaps you should remove the ';' from this line" message, but it's an extra bit of cognitive overhead induced by case statements.

Ultimately, I think it's less about missing syntactic sugar, and more about the type system acting like an electric fence instead of a hedge in its efforts to guide the user to their destination.

2 comments

> Explicit returns are frowned upon

That's not true in any of the code I write. I prefer explicit returns in all of my Rust code. The only time I use the "result from last expression" return is when it's the last statement in the function.

The recommended way to deal with errors in Rust is "try!". Using "try!" essentially gives you the ergonomics of exceptions. You should prefer that to match or .and_then(), which are verbose.

Explicit returns are not frowned upon. I don't know where you got that idea. The only thing I can think is that this:

    fn foo() -> bool {
        true
    }
is preferred over

    fn foo() -> bool {
        return true
    }
But that's more of a style issue.

As for `;`, it's just like Standard ML. `;` is for sequencing expressions. I love it.

> Explicit returns are not frowned upon. I don't know where you got that idea

From the docs:

http://doc.rust-lang.org/book/functions.html

> Using a `return` as the last line of a function works, but is considered poor style

Right -- explicit returns are frowned upon in the last line of a function, because they're absolutely not necessary, but everywhere else they're kosher.
Yes. Which is what I said. "Using a `return` as the last line of a function works" is not the same as "don't use explicit returns."
So I should use `return` except when I shouldn't? This is the cognitive overhead problem I'm talking about.

The original context of my concern is the instance where the match statement makes up the last statement in the function (frequently the only statement in the function's immediate scope). Since the individual cases are not terminating the function early, to get a value out of a match statement you simply leave the last expression bare.

i.e.

    fn something... {
      match input {
      Ok(input_val) => {/* several lines of semicolon terminated code*/
                        output}
      Err(errval) => {/* several more lines of semicolon terminated code */
              output}
    } 
is correct, but

    fn something... {
      match input {
      Ok(input_val) => {/* several lines of semicolon terminated code*/
                        return output;}
      Err(errval) => {/* several more lines of semicolon terminated code */
              return output;}
    } 
is poor style, and

    fn something... {
      match input {
      Ok(input_val) => {/* several lines of semicolon terminated code*/
                        output;}
      Err(errval => {/* several more lines of semicolon terminated code */
              output;}
    } 
is an error.
> So I should use `return` except when I shouldn't? This is the cognitive overhead problem I'm talking about.

No. Use `return` only when you must. If you want an early return in a function, then you need to use `return`. If you don't need an early return, then don't use `return` at all.

I can't remember if this was ever a cognitive load for me personally. I don't think it was.

> I can't remember if this was ever a cognitive load for me personally. I don't think it was.

Well, to be fair, it sounds like you're used to semicolons having special meaning (aside from separating expressions) from a previous language.

> As for `;`, it's just like Standard ML. `;` is for sequencing expressions. I love it.

It's worth remembering that most users of C, C++, Ruby, Java, Python, or whathaveyou are not used to the semicolon having special meaning. Since Rust appears to be primarily aimed at replacing C++, this is going to be a significant change which will likely trip people up for awhile.

> This is the cognitive overhead problem I'm talking about.

The cognitive overhead of having the value of a function be the last expression in it is incredibly minor; lots of languages have this feature. Even JavaScript and C# have this with their arrow functions.

> …is an error.

The only time you get an error is if you tried to do something that you couldn't do in C++ at all (returning a value without typing return). I don't see how that would confuse C++ programmers. C++ programmers who write Rust using explicit returns everywhere will have their programs work exactly as they expect.

>The cognitive overhead of having the value of a function be the last expression in it is incredibly minor; lots of languages have this feature.

This can cause performance problems in Coffescript because for loops are also expressions.