4 ms·
I haven't spent a lot of time with FP languages over the years, but implicit returns are one of my least favorite features of Rust. Especially the use of semic
by skohan 7y ago
I haven't spent a lot of time with FP languages over the years, but implicit returns are one of my least favorite features of Rust. Especially the use of semicolons to denote a terminated statement vs. a return value: a semicolon-related typo is such an easy mistake to make, and an annoying reason for a build to fail, especially when so many modern languages have shown it's quite possible and pleasant to work without semicolons.
- steveklabnik 7y agoTo be clear, Rust does not have "implicit returns" nor does it use semicolons to indicate return values. Expressions evaluate to a value, and semicolons take an expression, throw away its value, and evaluate to () instead. That's it. The other behaviors you're talking about fall out of these semantics, but are also different than what you've said; functions evaluate to a value, so the final expression's value determines the value it evaluates to, but you cannot "implicitly return" from the middle of a function by dropping a ;, for example.
- _bxg1 7y agoWhat I meant was the fact that you can omit the "return" keyword: fn foo(x: i32) -> i32 { x * 2 }
- steveklabnik 7y agoRight, but only as the last expression in a block, which is different than what "implicit returns" implies.
- skohan 7y agoIt's a bit of a semantic distinction isn't it? In practice what it means is that you add semicolons to the end of almost every line of imperative code in a block, and you leave the semicolon off the last line and this becomes your return value implicitly (without the use of a return keyword).
- steveklabnik 7y agoIt is a semantic distinction, because "everything is an expression" and "implicit returns" have different semantics. Thinking of them as implicit returns leads people to believe they can write code like fn foo(x: bool) -> i32 { if x { 5 } // more code and then they're confused when this doesn't work.
- _bxg1 7y agoI actually love the semicolon semantics. Making expressions and statements disjoint prevents bugs like this: if(foo = 5) { ... } They are easy to mess up when you're getting started, but they're also very easy to fix because they'll basically always result in a clear compiler error. If "builds failing" are annoying for you, you probably aren't using an IDE with inline errors, and with Rust you absolutely should be doing that or you'll have a bad time.
- skohan 7y agoif(foo = 5) { ... } You don't need the rust style expression/statement distinction to catch this. Many languages will catch this at compile time since "foo = 5" does not evaluate to a boolean. I know that it's relatively easy to catch this error in Rust, and it is at most a minor annoyance, but it still feels like a clear step backwards after working with languages which don't require semicolons at all.
- _bxg1 7y ago> since "foo = 5" does not evaluate to a boolean In most C-like languages, this expression is valid: the whole thing evaluates to "5", which has a truthiness. Some "clever" programmers use this pattern intentionally in loops to save a line of code, especially in the C/C++ world. For example: while(currentNode = currentNode.next) { ... } When currentNode becomes null, the expression/statement becomes falsy, and the loop terminates. I absolutely love the way Rust systematically disallows shaky syntax tricks like this.